cancel
Showing results for 
Search instead for 
Did you mean: 

ADC - watchdog

LucasStartTech
Associate III

@Amel NASRI @Tesla DeLorean 

Hi! I have a question about the ADC WD. I am trying to use it, being triggered by a touchscreen, I have set it as follow: 

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.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}

/** Configure the analog watchdog
*/
AnalogWDGConfig.WatchdogMode = ADC_ANALOGWATCHDOG_SINGLE_REG;
AnalogWDGConfig.HighThreshold = 0;
AnalogWDGConfig.LowThreshold = 0;
AnalogWDGConfig.Channel = ADC_CHANNEL_10;
AnalogWDGConfig.ITMode = ENABLE;
if (HAL_ADC_AnalogWDGConfig(&hadc1, &AnalogWDGConfig) != HAL_OK)
{
Error_Handler();
}

/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_10;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */

/* USER CODE END ADC1_Init 2 */

}

 

 

 

I did this in the while loop: 

HAL_ADC_Start_IT(&hadc1);
while (1)
{ // Define the correct framebuffer address

/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
if (cmd == 0x01){
cmd = 0x00;
// Reconfigure ADC to read from first channel (ADC_CHANNEL_11)
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = ADC_CHANNEL_12;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);

// Start the ADC and poll for completion
//HAL_ADC_Start(&hadc1);
//HAL_ADC_PollForConversion(&hadc1, 10); // Wait for conversion to complete with a timeout
//uhADCxConvertedValue = HAL_ADC_GetValue(&hadc1); // Read the value from ADC_CHANNEL_11

// Reconfigure ADC to read from second channel (ADC_CHANNEL_9)
sConfig.Channel = ADC_CHANNEL_10;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);

// Start the ADC and poll for completion
HAL_ADC_Start(&hadc1);
//HAL_ADC_PollForConversion(&hadc1, 10); // Wait for conversion to complete with a timeout
uhADCxConvertedValue = HAL_ADC_GetValue(&hadc1); // Add the value from ADC_CHANNEL_9
HAL_Delay(100);
sprintf(msg3, "Val: %d", uhADCxConvertedValue);
memset(buffer2, 255, sizeof(buffer2)); // Clear buffer
LCD_ShowString(buffer2, 100, 200, 16, msg3, 0);
HAL_Delay(100);
}

sprintf(msg3, "Val: Outside %d", uhADCxConvertedValue);
memset(buffer2, 255, sizeof(buffer2)); // Clear buffer
LCD_ShowString(buffer2, 100, 200, 16, msg3, 0);

}

 

And added this to set a flag when it is triggered: 

void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef* hadc)
{
/* Set variable to report analog watchdog out of window status to main */
/* program.
* */
cmd = 0x01;

__HAL_ADC_CLEAR_FLAG(&hadc1, ADC_FLAG_AWD);
__HAL_ADC_CLEAR_FLAG(&hadc1, ADC_FLAG_EOC);
__HAL_ADC_CLEAR_FLAG(&hadc1, ADC_FLAG_OVR);

HAL_ADC_Start_IT(&hadc1);

}

 

Then my issue comes when I set a safeguard region for the watch dog. Once I run the code, it all works fine and I can see it toggling the flag in the oscilloscope, however, as soon as I hit the safeguard value range, it stops triggering. 

 

If someone can help me!

 

Thank you!

2 REPLIES 2
TDK
Guru

Can you format the code using the </> tool? You've been here a while. It helps readability.

If you feel a post has answered your question, please click "Accept as Solution".

@TDK Hi! I am sorry for this! I've not used it until now! Let me redo it! I will also use the current version that I have.

Reading it I can see that I have provided no explanation whatsoever, so here is my ongoing goal.

NOTE: This is the first time I work with ADC and try to control a touchscreen myself.

I was able to design a new board using a STM32F469IIT6, besides other things that I have added onto the board, the current question is regarding my intention on controlling the touchscreen. Since it is a prototype, I have connected the pins for the screen in two ways, which I can control the direction using 4 jumpers. The first way that I can get control of the touchscreen is using a XPT2046 that I have added to the board, in case of not being able to use the ADC, so I would have something to work on, until I could fix any wiring mistake when trying to control it directly with ADC pins.

So, I was able to control it with the XPT2046, however it is very slow doing this way, since first I have to send command using SPI, which already takes time, and what is worse, I have to reduce the Baud Rate, because the XPT is slower than my STM. Therefore, my goal is now to migrate from using a external controller and drive the touch screen directly. 

Working with the ADC, I was then able to read the signal, and the response is much, much better than when using the XPT. However, the only challenge I am currently facing is to set up an interrupt. I can't use the polling mode because I have other communications that I am expecting to receive from external devices and then I can't be blocking them to read the screen. 

I've set up my ADC as follow, I will put it into 2 parts:

PART I - ADC configuration

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.ScanConvMode = ENABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 2;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure the analog watchdog
  */
  AnalogWDGConfig.WatchdogMode = ADC_ANALOGWATCHDOG_SINGLE_REG;
  AnalogWDGConfig.HighThreshold = 0;
  AnalogWDGConfig.LowThreshold = 0;
  AnalogWDGConfig.Channel = ADC_CHANNEL_9;
  AnalogWDGConfig.ITMode = ENABLE;
  if (HAL_ADC_AnalogWDGConfig(&hadc1, &AnalogWDGConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_9;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_10;
  sConfig.Rank = 2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}

 

PART II - ADC callback

void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef* hadc)
{
    if (hadc->Instance == ADC1) {
    	adcs[0] = HAL_ADC_GetValue(hadc);
    	adcs[1] = HAL_ADC_GetValue(hadc);
    	cmd = 0x01;

        __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD);
        __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOC);
        __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_OVR);

        HAL_ADC_Start_IT(hadc);
    }
}

 

With this, I was able to read the screen and use the interrupt but with some issues.

1) I expected to have 0 or a low value when trying nothing was touching the screen, however I constantly read a value that stands between the maximum value I can get and the minimum value I can get when I touch the screen. With this issue I would have to sacrifice part of the screen as non-detectable almost in the middle of the screen.

2) I did then set the watchdog "safeguard" region, to test if it would work, however for some reason, every time the reading hit a value within the safeguard range, the ADC_IT stopped triggering, as if it was in some race condition. I could confirm that the while loop works just fine, but it never went to the callback again.

 

Along with this, I also have a question regarding the way I am trying to use the ADC. Here is my schematic:

LucasStartTech_0-1744649858382.png

The ADC pins are connected to the touch screen in this very straightforward way. I wonder if this approach was correct, or if I am missing some pull up/down. Because, if I am not getting it wrongly, I need to drive the pins from left/right to right/left and read from up/down to down/up. It was very easy to do, however once I do it, I have then to change the GPIO configurations for all 4 pins. My concern is, if this approach is correct or if I should add some component to my schematic. I've tried to forcedly drive the pins with others. connecting them together, but the readings were terrible.

 

I really appreciate the patient you all have been having with my questions!

If needed I can also provide the whole schematic.