Hi guys, I’m trying to set up Analog WatchDog on a Bluepill with FreeRTOS, but I can’t find any documentation about it.
All I find is using the “STM32CubeIDE” application, but I need to be able to configure and program it directly from my PlatformIO code.
Basically, I need an interrupt to be triggered when an analog pin reaches a certain voltage. I’d also like to know if I can change this voltage in real time, based on other input parameters.
I use:
framework = arduino
In code: #include <STM32FreeRTOS.h>
Can anyone help me?
Regards!
I don’t see there being a ready-made Arduino library that wraps the Analog Watchdog functionality, but since the Arduino core is built on top of the STM32HAL, you can call into normally.
Below is an example for PA0 and the some voltage threshholds. You should be able to reconfigure the upper and lower voltages on the fly by just writing
WRITE_REG(hadc->Instance->HTR, HighThreshold);
WRITE_REG(hadc->Instance->LTR, LowThreshold);
as needed. In the interrupt / calllback function HAL_ADC_LevelOutOfWindowCallback, you may of course also use a FreeRTOS primitive to send a notification to a FreeRTOS task, causing it to wake up, instead of setting a volatile bool variable here. Also see https://deepbluembedded.com/stm32-analog-watchdog-adc-mode-code-example/ for reference.
#include <Arduino.h>
/* Example: PA0 */
#define ADC_PORT GPIOA
#define ADC_PIN GPIO_PIN_0 // Change to any ADC-capable pin
#define USED_ADC ADC1 // Change to ADC2 if using ADC2
#define GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define ADC_CHANNEL ADC_CHANNEL_0 // must match pin (or special internal channel)
/* trigger analog watchdog if below LOW or above HIGH */
#define LOW_THRESHOLD 1000 // 0–4095 (12-bit ADC)
#define HIGH_THRESHOLD 3000 // 0–4095
ADC_HandleTypeDef hadc;
volatile bool watchdogTriggered = false;
void SystemClock_Config(void);
void MX_ADC_Init(void);
void setup() {
Serial.begin(115200);
delay(2000);
Serial.println("Analog Watchdog Example");
// Enable all ADC clocks to be safe
__HAL_RCC_ADC1_CLK_ENABLE();
__HAL_RCC_ADC2_CLK_ENABLE();
MX_ADC_Init();
// Start ADC in interrupt mode
HAL_StatusTypeDef status = HAL_ADC_Start_IT(&hadc);
if (status != HAL_OK) {
Serial.println("Failed to start ADC interrupt mode");
} else {
Serial.println("ADC started in interrupt mode");
}
}
void loop() {
// check if the watchdog was triggered and print a message
if (watchdogTriggered)
{
watchdogTriggered = false;
Serial.println("⚠ Analog Watchdog Triggered!");
}
delay(10);
}
void MX_ADC_Init(void) {
GPIO_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = ADC_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(ADC_PORT, &GPIO_InitStruct);
ADC_ChannelConfTypeDef sConfig = {0};
ADC_AnalogWDGConfTypeDef awdConfig = {0};
hadc.Instance = USED_ADC;
hadc.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc.Init.ContinuousConvMode = ENABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.NbrOfConversion = 1;
HAL_ADC_Init(&hadc);
// Configure selected ADC channel
uint32_t channel = ADC_CHANNEL;
sConfig.Channel = channel;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;
HAL_ADC_ConfigChannel(&hadc, &sConfig);
// Configure Analog Watchdog
awdConfig.WatchdogMode = ADC_ANALOGWATCHDOG_SINGLE_REG;
awdConfig.Channel = channel;
awdConfig.ITMode = ENABLE;
awdConfig.HighThreshold = HIGH_THRESHOLD;
awdConfig.LowThreshold = LOW_THRESHOLD;
HAL_ADC_AnalogWDGConfig(&hadc, &awdConfig);
// Enable ADC interrupt in NVIC
HAL_NVIC_SetPriority(ADC1_2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(ADC1_2_IRQn);
}
/* Interrupt handler */
extern "C" void ADC1_2_IRQHandler(void) {
HAL_ADC_IRQHandler(&hadc);
}
/* callback from STM32HAL if watchdog triggered */
extern "C" void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef *hadc) {
watchdogTriggered = true;
}
Thanks for your reply, will try it…