cancel
Showing results for 
Search instead for 
Did you mean: 

WHILE LOOP PROBLEM FOR MICRO SECONDS WITH TIMER ??

Ramazan Gülcan
Associate III
Posted on June 16, 2018 at 22:25

Hi friends,

The while loop does not work in the following function. Why could it be?

For STM32F407VG;

void US_BEKLE(uint16_t us)

{

uint16_t baslangic = (uint16_t)__HAL_TIM_GET_COUNTER(&htim1);

while(((uint16_t)__HAL_TIM_GET_COUNTER(&htim1)) - baslangic < us);

}

htim1.Instance = TIM1;

htim1.Init.Prescaler = 167;

htim1.Init.CounterMode = TIM_COUNTERMODE_UP;

htim1.Init.Period = 65000;

htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

htim1.Init.RepetitionCounter = 0;

#microsecond-timer #while-loop
1 ACCEPTED SOLUTION

Accepted Solutions
Posted on June 17, 2018 at 14:07

I solved the problem. As I said, there was a problem when the subtraction was negative. It worked smoothly in the following manner.

void US_BEKLE(uint16_t us)

{

uint16_t baslangic = (uint16_t)__HAL_TIM_GET_COUNTER(&htim1);

while((((uint16_t)__HAL_TIM_GET_COUNTER(&htim1)) - baslangic < us) && (baslangic - ((uint16_t) __HAL_TIM_GET_COUNTER(&htim1))  <  (65535 - us)) );

}

Thanks

View solution in original post

13 REPLIES 13
Tilen MAJERLE
ST Employee
Posted on June 16, 2018 at 22:29

Hello,

please clarify 'it doesn't work'. Please check some of these questions:

  1. Is the timer running?
  2. Do you use optimizations and while loop was optimized out?
  3. Is your delay longer or shorter than expected?

Best regards,

Tilen

Posted on June 16, 2018 at 23:37

For the math to work you want

htim1.Init.Period = 65535;

try this

void US_BEKLE(uint16_t us)

{

uint16_t baslangic = (uint16_t)__HAL_TIM_GET_COUNTER(&htim1);

while( (uint16_t)(__HAL_TIM_GET_COUNTER(&htim1) - baslangic) < us);

}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on June 16, 2018 at 22:40

hi,

timer is running.

I do not use optimization.

I want to run the delay time for 20 us as an example.

henry.dick
Senior II
Posted on June 17, 2018 at 00:47

'

Why could it be?'

look up integer promotion. the simplest yet most complex aspect of C.

Posted on June 17, 2018 at 00:21

htim1.Init.Period = 65535;

unfortunately did not work

Posted on June 17, 2018 at 00:32

I think it's a problem because the subtraction process is not an absolute value. 

for example; 

us=500

baslangic=65500

current get timer = 300 (autoreload overflow after from 65535  - > +1 CNT = 0 ) 

substract = 300 - 65500 = -65200

because -65200 < 500 while loop is constantly going on

As a solution, the absolute value must be applied, or the timer module must be reset each time.

Posted on June 17, 2018 at 00:43

That's not how unsigned 16-bit math works. Also for the wrapping to work properly the Period needs to be 0xFFFF (65535)

336 < 500

Perhaps the HAL function is masking the volatile nature of the peripheral register, assuming optimization involved.

void US_BEKLE(uint16_t us)

{

uint16_t baslangic = (uint16_t)TIM1->CNT;

while( (uint16_t)(TIM1->CNT - baslangic) < us);

}

And your complaint is that it isn't exiting the loop?

What tool chain is involved here?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on June 17, 2018 at 02:59

this is a similar issue to

Turvey.Clive.002

mention of HAL_timeout.

change the order of calculation, (but this is not a good solution)

void US_BEKLE(uint16_t us)

{

uint16_t endTime = (uint16_t)TIM1->CNT + us

while( (uint16_t)(TIM1->CNT ) != endTime); // must be exact, so can fail, if the timer is tooo fast.

}

the problem there is that you may miss a count, just when you need it.. depending on the clocking rate.

I suggest that you use the output compare function of the timer, to be sure that you have a hit.

void US_BEKLE(uint16_t us)

{

uint16_t endTime = (uint16_t)TIM1->CNT + us

// set OutputCompare to endTime

htim->Instance->CCR1 =endTime;

// wait for OC flag;

while( ! htim->Instance->SR & TIM_SR_CC1IF)

;

}

Posted on June 17, 2018 at 14:07

I solved the problem. As I said, there was a problem when the subtraction was negative. It worked smoothly in the following manner.

void US_BEKLE(uint16_t us)

{

uint16_t baslangic = (uint16_t)__HAL_TIM_GET_COUNTER(&htim1);

while((((uint16_t)__HAL_TIM_GET_COUNTER(&htim1)) - baslangic < us) && (baslangic - ((uint16_t) __HAL_TIM_GET_COUNTER(&htim1))  <  (65535 - us)) );

}

Thanks