今天和大家分享一下使用内部的模拟看门口监测内部ADC阈值的方法。
首先简单和大家分享一下,STM32内部几种看门狗的知识和区别;
STM32微控制器中的看门狗(Watchdog)用于监控系统运行状态,防止程序跑飞或死锁。STM32提供了三种看门狗:独立看门狗(IWDG)、窗口看门狗(WWDG)和模拟看门狗(Analog Watchdog)。它们的主要区别如下:
1. 独立看门狗(IWDG)
功能:独立看门狗是一个简单的定时器,用于检测系统是否正常运行。如果系统未在规定时间内刷新看门狗,看门狗将复位系统。
时钟源:使用独立的低速内部时钟(LSI),频率通常为32kHz,不受主时钟影响。
配置:可设置超时时间,超时后复位系统。
应用场景:适用于需要高可靠性的系统,确保系统在异常情况下复位。
2. 窗口看门狗(WWDG)
功能:窗口看门狗不仅要求在规定时间内刷新,还要求在特定时间窗口内刷新。过早或过晚刷新都会导致复位。
时钟源:使用APB1总线时钟,频率较高。
配置:可设置窗口的上限和下限,刷新时间必须在窗口内。
应用场景:适用于需要精确监控任务执行时间的系统,确保任务按时完成。
3. 模拟看门狗(Analog Watchdog)
功能:模拟看门狗用于监控模拟信号(如ADC输入),当信号超出设定范围时触发中断或事件。
时钟源:无独立时钟,依赖ADC模块。
配置:可设置上下限阈值,监控模拟信号是否在范围内。
应用场景:适用于需要监控模拟信号的应用,如电池电压、温度传感器等。
总结:
独立看门狗:简单可靠,适用于系统复位。
串口看门狗:精确监控任务执行时间,适用于时间敏感任务。
模拟看门狗:监控模拟信号,适用于模拟信号监控。
根据具体需求选择合适的看门狗类型。
今天重点和大家分享模拟看门狗的知识;我们可以在STM32cube MX 中开启模拟看门狗功能;如下所示:

配置一下ADC1的基本参数,如下所示:

软件代码如下所示:
初始化ADC参数,开始模拟看门狗的功能,配置ADC引脚功能,这里需要注意一下,ADC引脚需要配置成输入模式;
static void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 0 */
ADC_AnalogWDGConfTypeDef AnalogWDGConfig = {0};
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
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_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.LowPowerAutoPowerOff = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_160CYCLES_5;
hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_160CYCLES_5;
hadc1.Init.OversamplingMode = DISABLE;
hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure Analog WatchDog 1
*/
AnalogWDGConfig.WatchdogNumber = ADC_ANALOGWATCHDOG_1;
AnalogWDGConfig.WatchdogMode = ADC_ANALOGWATCHDOG_ALL_REG;
AnalogWDGConfig.ITMode = ENABLE;
AnalogWDGConfig.HighThreshold = ADC_AWD_THRESHOLD_HIGH;
AnalogWDGConfig.LowThreshold = ADC_AWD_THRESHOLD_LOW;
if (HAL_ADC_AnalogWDGConfig(&hadc1, &AnalogWDGConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_4;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */
/* USER CODE END ADC1_Init 2 */
}软件代码监控ADC值的代码监测:
/**
* @brief Rearm ADC analog watchdog to make it ready another trig
* (ADC handle: hadc1, analog watchdog instance: AWD1).
* @param None
* @retval None
*/
void ADC_AnalogWatchdog_Rearm(void)
{
/* Clear flag ADC analog watchdog 1 */
__HAL_ADC_CLEAR_FLAG(&hadc1, ADC_FLAG_AWD1);
/* Enable ADC analog watchdog 1 interruption */
__HAL_ADC_ENABLE_IT(&hadc1, ADC_IT_AWD1);
}
/******************************************************************************/
/* USER IRQ HANDLER TREATMENT */
/******************************************************************************/
/**
* @brief Analog watchdog callback in non blocking mode.
* @param hadc: ADC handle
* @retval None
*/
void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef* hadc)
{
/* Disable ADC analog watchdog 1 interruption */
/* Note: ADC analog watchdog 1 interruption rearmed afterwards after
event processing completion */
__HAL_ADC_DISABLE_IT(hadc, ADC_IT_AWD1);
/* Retrieve ADC conversion data */
/* Note: data scale corresponds to ADC resolution */
uhADCxConvertedData = HAL_ADC_GetValue(hadc);
/* Update status variable of ADC analog watchdog 1 */
ubAnalogWatchdog1Status = 1;
/* Change LED toggle frequency depending on voltage below or above
analog watchdog window */
if (uhADCxConvertedData > ADC_AWD_THRESHOLD_HIGH)
{
led_toggle_period_ms = LED_BLINK_VERY_FAST;
}
else /* (uhADCxConvertedData < ADC_AWD_THRESHOLD_LOW) */
{
led_toggle_period_ms = LED_BLINK_FAST;
}
/* Set ADC analog watchdog rearm delay iterations count */
adc_awd_rearm_delay_iterations_count = (ADC_AWD_REARM_DELAY_MS / led_toggle_period_ms);
}主程序代码如下所示:
if(ubAnalogWatchdog1Status == 1)
{
/* Wait for ADC analog watchdog rearm */
adc_awd_rearm_delay_iterations_count--;
if(adc_awd_rearm_delay_iterations_count == 0)
{
led_toggle_period_ms = LED_BLINK_SLOW;
/* Reset status variable of ADC analog watchdog 1 */
ubAnalogWatchdog1Status = 0;
/* Rearm ADC analog watchdog to make it ready for another trig */
ADC_AnalogWatchdog_Rearm();
}
}
BSP_LED_Toggle(LED4);
HAL_Delay(led_toggle_period_ms);实物验证如下:
如下图所示:将电位器模块接入到STM32U083RC的开发板上,旋转电位器可以看到LED灯不同效果的闪烁过程。
整个测试的试验流程:从主程序执行开始,ADC连续转化所选的通道4,当内部ADC监测到超出模拟看门狗窗口时,CPU产生ADC中断,并调用模拟看门狗回调函数来处理事件,处理时间间隔5秒,ADC模拟看门口重新准备,为下次产生ADC中断做好准备。
为了方便看到ADC的检测值的数据,这里i用LED灯的闪烁频率间接显示数据:
LED4 用于监控程序执行状态:
正常工作:可以通过 LED 切换频率观察 ADC 通道监控通道窗口与模拟看门狗窗口的电压:模拟看门狗窗口内的电压:切换频率慢 (2Hz)
电压低于模拟看门狗窗口:快速切换频率 (10Hz)
电压高于模拟看门狗窗口:切换频率非常快 (20Hz)
错误:LED 指示灯仍亮起

我要赚赏金
