Skip to main content
SA.17
Associate III
May 20, 2020
Solved

How to ensure UART transmits data every second ?

  • May 20, 2020
  • 10 replies
  • 2617 views

Hi,

I am using STM32L0 MCU

I am using HAL_USART_TRANSMIT function to send data to a computer

I am using Timer interrupt to ensure that UART transmits data every second

But when i see log on computer ,its not exactly 1 sec, and this change also varies with baudrate ,so if Baud rate is 115200 ,getting data on uart every 1.3 sec (approx.) and it is not same everytime,whereas with 9600 it is slower .

How to ensure that uart sends data at every 1sec ( with HAL API or LL API or any other way) ?

timer code(using systick timer)

 

void SysTick_Handler(void)
 
 {
 
 /* USER CODE BEGIN SysTick_IRQn 0 */
 
 /* USER CODE END SysTick_IRQn 0 */
 
 HAL_IncTick();
 
 /* USER CODE BEGIN SysTick_IRQn 1 */
 
if(flag_uart_delay == 0)
 
 {
 
 counter_uart ++ ;
 
 if(counter_uart >= 1000)
 
 {
 
 flag_uart_delay = 1 ;
 
 counter_uart = 0;
 
 }
 
 }
 
}

Main Code

 

if(flag_uart_delay == 1)
 
{
 
//HAL_TRANSMIT_DATA ( ... )
 
flag_uart_delay = 0 ;
 
}

This topic has been closed for replies.
Best answer by Guenael Cadier

This is my understanding after reading your code.

With current code, during transmission, flag_uart_delay is 1, so all SysTick Handler execution during the UART TX phase, have no impact on counter_uart which remains = 0. counter_uart increments will restart after TX, once flag_uart_delay is reset to 0.

What you have now is :

<--- 1 sec period ----><--TX--><--- 1 sec period ----><--TX--><--- 1 sec period ----> ...

If you want to have :

<--- 1 sec period ----><--- 1 sec period ----><--- 1 sec period ----> ...
<--TX--> <--TX--> <--TX-->

You need either :

  • to still increment timer during the Tx (by setting flag_uart_delay = 0 after TX start if you use polling mode)
  • to use IT or DMA mode for ensuring TX process. IT and MDA API calls only initiate the TX steps, and function exit (return to main() will not need that TX is ended

Guenael

10 replies

waclawek.jan
Super User
May 20, 2020

Is that a regular timer interrupt, triggered by timer Update? You don't change anything with the timer within that interrupt, do you?

Show code.

JW

SA.17
SA.17Author
Associate III
May 20, 2020

added code in question

SA.17
SA.17Author
Associate III
May 20, 2020

I am using systick timer,not changed anything in timer configuration,used the code as it is generated by stm32cubemx

Ozone
Principal
May 20, 2020

> But when i see log on computer ,its not exactly 1 sec, and this change also varies with baudrate ,so if Baud rate is 115200 ,getting data on uart every 1.3 sec (approx.) and it is not same everytime,whereas with 9600 it is slower .

How sure you are about the measurements on PC side ? Windows is no RT OS either.

Toggle a pin during UART send, and check with a scope.

If you find that same large variance with a scope, you can use the same method to find out where the "lost" MCU time is spent.

SA.17
SA.17Author
Associate III
May 20, 2020

I am using Tera term on computer to receive it ,and have enabled time on it,so whenever it(tera term) receives signal it attaches time and date to log (where time and date are taken from computer clock) . Even if windows is not RTOS ,clock is always accurate on it

, I will try with oscilloscope

Tesla DeLorean
Guru
May 20, 2020

Measure signal with a scope to be sure to know where the issue is. Probably not the time base of the STM32 with a crystal.

Check clocks parameters and dividers.​

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Guenael Cadier
ST Employee
May 20, 2020

Hi @SA.17​ 

Are you using HAL UART transmit API in Polling mode (HAL_UART_Transmit() API) ?

If so, this means that in your main(), flag_uart_delay variable, once set to 1 in Systick Handler, will be set to 0 again after transmission time, so depends on baudrate and nb of transmitted data.

In such case, 1 sec time period is not the time between the start of 2 TX sequences, but rather the time between end of last Tx sequence, and start of next one.

Guenael

SA.17
SA.17Author
Associate III
May 20, 2020

yes i am using polling mode,

you mean to say i should make flag_uart_delay variable set to 0 before using UART transmit API

or should i use it in interrupt mode

Guenael Cadier
Guenael CadierBest answer
ST Employee
May 20, 2020

This is my understanding after reading your code.

With current code, during transmission, flag_uart_delay is 1, so all SysTick Handler execution during the UART TX phase, have no impact on counter_uart which remains = 0. counter_uart increments will restart after TX, once flag_uart_delay is reset to 0.

What you have now is :

<--- 1 sec period ----><--TX--><--- 1 sec period ----><--TX--><--- 1 sec period ----> ...

If you want to have :

<--- 1 sec period ----><--- 1 sec period ----><--- 1 sec period ----> ...
<--TX--> <--TX--> <--TX-->

You need either :

  • to still increment timer during the Tx (by setting flag_uart_delay = 0 after TX start if you use polling mode)
  • to use IT or DMA mode for ensuring TX process. IT and MDA API calls only initiate the TX steps, and function exit (return to main() will not need that TX is ended

Guenael

waclawek.jan
Super User
May 20, 2020

@Guenael Cadier​  is right.

So, just throw away the

> if(flag_uart_delay == 0)

from the systick interrupt, and leave the rest, and you should be good.

JW