cancel
Showing results for 
Search instead for 
Did you mean: 

Why does HAL_UART_TRANSMIT block my adc routine?

MVan.16
Associate II

I am using stm32cube with the HAL functions to start my project. I have everything running fine. I have my adc trigger using OCP2 of my pwm and this works like a charm. But wen i use the uart somehow my adc does not want to trigger anymore and i do not get any interrupts for the adc anymore. How can the UART do this even when it does not use interrupts?

7 REPLIES 7
Bob S
Principal

Please post your code. Otherwise its just pot shots in the dark. Which style of HAL functions are you using: polled, interrupt or DMA? If the answer is "polled", my response is "don't do that".

Depends where you use it. If you use the HAL UART Transmit in a callback it can block interrupts. Callbacks are done under interrupt context.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Sorry, here is my code.

int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
  
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ADC3_Init();
  MX_DAC1_Init();
  MX_ETH_Init();
  MX_HRTIM_Init();
  MX_TIM2_Init();
  MX_UART4_Init();
  MX_USB_OTG_FS_PCD_Init();
  /* USER CODE BEGIN 2 */
 
  HAL_HRTIM_WaveformCountStart(&hhrtim,(HRTIM_TIMERID_MASTER | HRTIM_TIMERID_TIMER_A | HRTIM_TIMERID_TIMER_C));//start master,timer A and timer C
  HAL_HRTIM_WaveformOutputStart(&hhrtim,(HRTIM_OUTPUT_TA1 | HRTIM_OUTPUT_TA2 | HRTIM_OUTPUT_TC1 | HRTIM_OUTPUT_TC2)); //enable hrtimer A en C outputs
 
  HAL_DAC_Start(&hdac1, DAC_CHANNEL_1); //enable DAC output 1, this sends the scaled ADC value to pin PA4
 
  HAL_ADC_Start_IT(&hadc3); //enable ADC
 
 
 
  HAL_TIM_OC_Start(&htim2, TIM_CHANNEL_1);//start TIM2 that is used for data trigger and use polling not interrupt
 
  //HAL_ADC_Start_DMA(&hadc3, (uint32_t *)adc_array, (uint32_t)1);
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
 
		if(check_timer_interrupt_flag_set(&htim2,OC1_FLAG)) //check if OC_INTERRUPT has passed
		{
		HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_9); // toggle pin E9
		send_info_uart();
		}
  }
  /* USER CODE END 3 */
}
void send_info_uart(void)
{
	HAL_UART_Transmit(&huart4,(uint8_t *)aTxBuffer, sizeof(aTxBuffer),500)
 
}
 
uint8_t check_timer_interrupt_flag_set(TIM_HandleTypeDef *handle,uint32_t number)
{
if(handle->Instance->SR & number)
	{
	handle->Instance->SR ^= number;
	return 1;
	}
else
	{return 0;}
 
}
 
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
	HRTIM_CompareCfgTypeDef timera_comp,adc_comp;
	//adc_converted_value=adc_array[0];
	adc_converted_value = HAL_ADC_GetValue(&hadc3);
 
	float temp = adc_converted_value*0.00763;
 
 
	timera_comp.CompareValue = (uint16_t) temp;
	if(timera_comp.CompareValue<3){timera_comp.CompareValue=3;}
	HAL_HRTIM_WaveformCompareConfig(&hhrtim, HRTIM_TIMERINDEX_TIMER_A, HRTIM_COMPAREUNIT_1, &timera_comp);
	HAL_HRTIM_WaveformCompareConfig(&hhrtim, HRTIM_TIMERINDEX_TIMER_C, HRTIM_COMPAREUNIT_1, &timera_comp);
	adc_comp.CompareValue = (uint16_t) (temp / 2 );
	HAL_HRTIM_WaveformCompareConfig(&hhrtim, HRTIM_TIMERINDEX_TIMER_A, HRTIM_COMPAREUNIT_2, &adc_comp);
 
	HAL_DAC_SetValue(&hdac1,DAC_CHANNEL_1,DAC_ALIGN_12B_R,(adc_converted_value*0.0625));
	//HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_9);
 
 
}

S.Ma
Principal

The SW architecture looks weird.

First, don't use float inside an interrupt (callback), you can most of the time use a int32_t temp_x100000 = adc_converted_Value *763;

Then in the main loop you look for a Timer status flag. Where will it be cleared for next time it's going to be tested?

USART send or receive take time (115200bps = 100usec per byte, so if core runs at 80MHz, that's 8000 cycles... significant.

The check_timer_interrupt_flag_set function resets the flag. It seems i found the problem. I use timer a compare 2 to trigger my adc. This has to do with current meas. I want to adjust this every time i trigger so that when i the adc samples it is always in the middle of the duty cycle. When i do this my adc loses its trigger. When i put this in comment there is no problem. I just need to find a solid way to make sure the adc triggers every cycle in the middle of the duty cycle.

solved the problem by making the variable in the interrupt static.

MVan.16
Associate II

solved the problem by making the variable in the interrupt static.Now it does what it should do.