Skip to main content
MVan.16
Associate
August 30, 2019
Question

Why does HAL_UART_TRANSMIT block my adc routine?

  • August 30, 2019
  • 4 replies
  • 1292 views

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?

This topic has been closed for replies.

4 replies

Bob S
Super User
August 30, 2019

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".

MVan.16
MVan.16Author
Associate
August 30, 2019

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);
 
 
}

Tesla DeLorean
Guru
August 30, 2019

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 VenmoUp vote any posts that you find helpful, it shows what's working..
S.Ma
Principal
August 30, 2019

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.

MVan.16
MVan.16Author
Associate
August 30, 2019

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.

MVan.16
MVan.16Author
Associate
August 30, 2019

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

MVan.16
MVan.16Author
Associate
August 30, 2019

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