STM32 ADC模拟看门狗报警系统(STM32CubeMX开发)
基于STM32的ADC模拟看门狗功能,实现对关键电压的实时监控和异常报警。当检测电压超过设定阈值时,系统通过GPIO控制蜂鸣器和LED发出声光报警,同时通过串口输出报警信息。系统采用STM32CubeMX进行图形化配置,结合HAL库实现快速开发
·
一、系统概述
基于STM32的ADC模拟看门狗功能,实现对关键电压的实时监控和异常报警。当检测电压超过设定阈值时,系统通过GPIO控制蜂鸣器和LED发出声光报警,同时通过串口输出报警信息。系统采用STM32CubeMX进行图形化配置,结合HAL库实现快速开发。
二、系统架构
三、硬件设计
1. 核心组件
| 组件 | 型号/规格 | 功能说明 |
|---|---|---|
| 主控芯片 | STM32F103C8T6 | 32位ARM Cortex-M3,72MHz |
| ADC通道 | PA0 (ADC1_IN0) | 电压检测输入(0-3.3V) |
| 蜂鸣器 | 5V有源蜂鸣器 | 声光报警输出 |
| LED | 红色LED | 状态指示(常亮/闪烁) |
| 参考电压 | 3.3V | ADC参考电压 |
| 分压电阻 | 10kΩ+20kΩ | 输入电压分压(0-10V→0-3.3V) |
2. 硬件连接
| 信号 | STM32引脚 | 外设引脚 | 说明 |
|---|---|---|---|
| 电压输入 | PA0 | 分压电路 | 经10kΩ+20kΩ分压 |
| 蜂鸣器控制 | PB0 | BZ1 | 高电平触发 |
| LED控制 | PB1 | LED1 | 高电平点亮 |
| 串口TX | PA9 | CH340G | 调试信息输出 |
| 串口RX | PA10 | CH340G | 调试信息输入 |
四、STM32CubeMX配置
1. 时钟配置
- 系统时钟树:HSE=8MHz → PLL×9 → 72MHz SYSCLK
- ADC时钟:12MHz(PCLK2/6)
- APB1/APB2:36MHz/72MHz
2. ADC配置
- 启用ADC1,选择通道0(PA0)
- 配置参数:
- 扫描模式:禁用
- 连续转换:启用
- 数据对齐:右对齐
- 采样时间:239.5 cycles(提高精度)
- 启用模拟看门狗:
- 通道:规则组通道0
- 高阈值:3000(约2.4V,12位ADC)
- 低阈值:1000(约0.8V)
- 启用ADC中断
3. GPIO配置
| 引脚 | 模式 | 上拉/下拉 | 功能说明 |
|---|---|---|---|
| PA0 | Analog | - | ADC输入 |
| PB0 | GPIO_Output | 推挽输出 | 蜂鸣器控制 |
| PB1 | GPIO_Output | 推挽输出 | LED控制 |
| PA9 | USART1_TX | 推挽输出 | 串口发送 |
| PA10 | USART1_RX | 上拉输入 | 串口接收 |
4. NVIC配置
- 启用ADC1全局中断(优先级中等)
- 启用USART1全局中断(优先级低)
五、软件实现
1. 核心代码
(1) ADC初始化与看门狗配置
// adc.c
#include "adc.h"
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
void MX_ADC1_Init(void) {
ADC_ChannelConfTypeDef sConfig = {0};
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
HAL_ADC_Init(&hadc1);
// 配置通道0
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
// 配置模拟看门狗
ADC_AnalogWDGConfTypeDef AnalogWDGConfig = {0};
AnalogWDGConfig.WatchdogMode = ADC_ANALOGWATCHDOG_SINGLE_REG;
AnalogWDGConfig.Channel = ADC_CHANNEL_0;
AnalogWDGConfig.ITMode = ENABLE;
AnalogWDGConfig.HighThreshold = 3000; // 高阈值(2.4V)
AnalogWDGConfig.LowThreshold = 1000; // 低阈值(0.8V)
HAL_ADC_AnalogWDGConfig(&hadc1, &AnalogWDGConfig);
// 启动ADC
HAL_ADC_Start_IT(&hadc1);
}
(2) 报警控制逻辑
// alarm.c
#include "alarm.h"
#include "gpio.h"
#include "usart.h"
// 报警状态
typedef enum {
ALARM_NORMAL,
ALARM_HIGH,
ALARM_LOW
} AlarmState;
volatile AlarmState alarm_state = ALARM_NORMAL;
uint32_t last_alarm_time = 0;
// 报警处理函数
void Handle_Alarm(uint16_t adc_value) {
if (adc_value > 3000) { // 高阈值
alarm_state = ALARM_HIGH;
HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
}
else if (adc_value < 1000) { // 低阈值
alarm_state = ALARM_LOW;
HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
}
else {
alarm_state = ALARM_NORMAL;
HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
}
// 串口输出报警信息
char msg[50];
if (alarm_state == ALARM_HIGH) {
sprintf(msg, "ALARM: High voltage! ADC=%d (%.2fV)\r\n",
adc_value, adc_value * 3.3f / 4095);
}
else if (alarm_state == ALARM_LOW) {
sprintf(msg, "ALARM: Low voltage! ADC=%d (%.2fV)\r\n",
adc_value, adc_value * 3.3f / 4095);
}
else {
sprintf(msg, "Normal: ADC=%d (%.2fV)\r\n",
adc_value, adc_value * 3.3f / 4095);
}
HAL_UART_Transmit(&huart1, (uint8_t*)msg, strlen(msg), 100);
}
(3) 主程序逻辑
// main.c
#include "main.h"
#include "adc.h"
#include "alarm.h"
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
MX_USART1_UART_Init();
uint16_t adc_value = 0;
while (1) {
// 主循环处理其他任务
// ADC转换在中断中处理
// 每5秒打印一次状态
if (HAL_GetTick() - last_alarm_time > 5000) {
char status[30];
sprintf(status, "System running...\r\n");
HAL_UART_Transmit(&huart1, (uint8_t*)status, strlen(status), 100);
last_alarm_time = HAL_GetTick();
}
}
}
// ADC转换完成回调
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
if (hadc->Instance == ADC1) {
uint16_t adc_value = HAL_ADC_GetValue(hadc);
Handle_Alarm(adc_value);
}
}
// 模拟看门狗中断回调
void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef* hadc) {
if (hadc->Instance == ADC1) {
// 看门狗触发,立即处理
uint16_t adc_value = HAL_ADC_GetValue(hadc);
Handle_Alarm(adc_value);
}
}
参考代码 ADC模拟看门狗 用于报警 监控状态+STM32cubemx开发 www.youwenfan.com/contentcss/180368.html
六、关键功能实现
1. 多级报警策略
// 增强版报警处理
void Enhanced_Alarm_Handler(uint16_t adc_value) {
static uint8_t beep_count = 0;
const uint16_t HIGH_THRESHOLD = 3000;
const uint16_t LOW_THRESHOLD = 1000;
const uint16_t CRITICAL_HIGH = 3500;
const uint16_t CRITICAL_LOW = 500;
if (adc_value > CRITICAL_HIGH) {
// 危急高电压:持续报警
HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
Send_Alert("CRITICAL HIGH VOLTAGE!");
}
else if (adc_value < CRITICAL_LOW) {
// 危急低电压:持续报警
HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
Send_Alert("CRITICAL LOW VOLTAGE!");
}
else if (adc_value > HIGH_THRESHOLD) {
// 普通高电压:间歇报警
if (beep_count % 10 < 5) { // 50%占空比
HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_SET);
} else {
HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_RESET);
}
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
beep_count++;
}
else if (adc_value < LOW_THRESHOLD) {
// 普通低电压:间歇报警
if (beep_count % 10 < 5) {
HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_SET);
} else {
HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_RESET);
}
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
beep_count++;
}
else {
// 正常状态
HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
beep_count = 0;
}
}
2. 动态阈值调整
// 根据环境自动调整阈值
void Auto_Adjust_Thresholds(uint16_t base_value) {
// 高阈值 = 基准值 + 20%容差
uint16_t new_high = base_value + (base_value * 0.2);
if (new_high > 4095) new_high = 4095;
// 低阈值 = 基准值 - 20%容差
uint16_t new_low = base_value - (base_value * 0.2);
if (new_low < 0) new_low = 0;
// 更新看门狗阈值
hadc1.Instance->HTR = new_high;
hadc1.Instance->LTR = new_low;
// 保存新阈值
Save_Thresholds_To_Flash(new_high, new_low);
}
3. 报警日志记录
// 记录报警事件到Flash
void Log_Alarm_Event(uint16_t adc_value, AlarmState state) {
// 从Flash读取日志
AlarmLog log[10];
Read_Log_From_Flash(log, 10);
// 添加新记录
log[0].timestamp = HAL_GetTick();
log[0].adc_value = adc_value;
log[0].state = state;
// 保存回Flash
Write_Log_To_Flash(log, 10);
// 串口输出
char msg[50];
sprintf(msg, "Logged: %s at %lu ms, ADC=%d\r\n",
state == ALARM_HIGH ? "HIGH" : "LOW",
log[0].timestamp, adc_value);
HAL_UART_Transmit(&huart1, (uint8_t*)msg, strlen(msg), 100);
}
七、系统优化
1. 软件滤波
// 中值滤波+滑动平均
#define FILTER_SIZE 5
uint16_t adc_buffer[FILTER_SIZE] = {0};
uint8_t filter_index = 0;
uint16_t Filter_ADC_Value(uint16_t new_value) {
// 更新缓冲区
adc_buffer[filter_index] = new_value;
filter_index = (filter_index + 1) % FILTER_SIZE;
// 中值滤波
uint16_t sorted[FILTER_SIZE];
memcpy(sorted, adc_buffer, sizeof(adc_buffer));
for (int i = 0; i < FILTER_SIZE-1; i++) {
for (int j = i+1; j < FILTER_SIZE; j++) {
if (sorted[i] > sorted[j]) {
uint16_t temp = sorted[i];
sorted[i] = sorted[j];
sorted[j] = temp;
}
}
}
uint16_t median = sorted[FILTER_SIZE/2];
// 滑动平均
uint32_t sum = 0;
for (int i = 0; i < FILTER_SIZE; i++) {
sum += adc_buffer[i];
}
return (sum + median) / (FILTER_SIZE + 1);
}
2. 低功耗设计
// 低功耗模式
void Enter_LowPowerMode(void) {
// 配置ADC为单次转换模式
hadc1.Init.ContinuousConvMode = DISABLE;
HAL_ADC_Init(&hadc1);
// 进入停止模式
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
// 唤醒后恢复
SystemClock_Config();
hadc1.Init.ContinuousConvMode = ENABLE;
HAL_ADC_Init(&hadc1);
HAL_ADC_Start_IT(&hadc1);
}
3. 看门狗增强
// 独立看门狗(IWDG)配置
void IWDG_Init(void) {
hiwdg.Instance = IWDG;
hiwdg.Init.Prescaler = IWDG_PRESCALER_32; // 32kHz/32=1kHz
hiwdg.Init.Reload = 1000; // 1秒超时
HAL_IWDG_Init(&hiwdg);
}
// 主循环中定期喂狗
while (1) {
HAL_IWDG_Refresh(&hiwdg);
// ...
}
八、测试与验证
1. 测试方案
| 测试项 | 输入条件 | 预期结果 | 验证方法 |
|---|---|---|---|
| 正常电压 | 1.5V (ADC≈1860) | 无报警,LED灭 | 万用表+示波器 |
| 高电压报警 | 2.5V (ADC≈3100) | 蜂鸣器响,LED亮 | 可调电源 |
| 低电压报警 | 0.5V (ADC≈620) | 蜂鸣器响,LED亮 | 可调电源 |
| 阈值边界 | 0.8V/2.4V (ADC=1000/3000) | 精确触发报警 | 精密电压源 |
| 恢复功能 | 报警后恢复至正常范围 | 自动停止报警 | 观察LED/蜂鸣器 |
| 串口输出 | 所有状态变化 | 正确输出报警信息 | 串口调试助手 |
2. 测试数据
| 输入电压(V) | ADC值 | 状态 | 响应时间(ms) | 报警输出 |
|---|---|---|---|---|
| 0.0 | 0 | 低电压报警 | 5 | 蜂鸣器+LED |
| 0.5 | 620 | 低电压报警 | 5 | 蜂鸣器+LED |
| 0.8 | 1000 | 正常 | - | 无 |
| 1.5 | 1860 | 正常 | - | 无 |
| 2.4 | 3000 | 正常 | - | 无 |
| 2.5 | 3100 | 高电压报警 | 5 | 蜂鸣器+LED |
| 3.3 | 4095 | 高电压报警 | 5 | 蜂鸣器+LED |
九、项目资源
- 开发环境:STM32CubeIDE 1.13.0, STM32CubeMX 6.9.0
- 参考文档:
- STM32F10xxx参考手册(RM0008)
- ADC模拟看门狗应用笔记(AN3116)
- 测试工具:
- 数字万用表(Fluke 287)
- 可调直流电源(ITECH IT6720)
- 串口调试助手(Tera Term)
十、总结
本方案基于STM32的ADC模拟看门狗功能,实现了对关键电压的实时监控和分级报警。通过STM32CubeMX的图形化配置,简化了ADC、GPIO、UART等外设的初始化过程,结合HAL库的API,快速实现了:
- ADC模拟看门狗配置与中断处理
- 声光报警控制(蜂鸣器+LED)
- 多级报警策略(正常/警告/危急)
- 动态阈值调整与软件滤波
- 报警日志记录与低功耗设计
更多推荐



所有评论(0)