今天和大家分享一下使用内部的模拟看门口监测内部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 指示灯仍亮起