2017-04-19 03:06 AM
I'm using HAL_TIM library for my timer proposal. I would like to count 100 us. My idea is starting to run a MCU timer in free run mode and having and interruption every this timer period. I have read there are several timers in my st used (stm32L476), and every timer has 3 or 4 channels: pwm, output mode, input capture, compare, etc.. But I don't know which will be the best for my proposal. I guess I can discard PWM modes or input capture mode, cause I only want to be internally counting time being passed, I don't want to be outputing any signal or reading an input pin.
Which is the channel or mode I must choose in order to have an interruption every 100us, 10us, or Xus? (of course I know I must handle the interruptions by sw but first I need to count period in the correct channel/mode)
Any help will be appreciate. Thanks in advance.
#timer-channels #hal #stm32l4-timer #hal_tim2018-06-21 05:04 PM
'
am I correct?'
not exactly. go through the link / code I provided earlier and try to understand how they work. it helps with a thorough understanding of the device / datasheet.
2018-06-21 05:24 PM
Hi
roseanne.qiu461
, looking beyond the technical details, I would like to know (if it's possible) what do you need to do with the timers? what is the smallest time that needs to be capture? and if you must to use all the timers with their interrupts? Sometimes answers are not in the how but the why... Thanks2018-06-21 06:05 PM
As I think I've mentioned before the Prescaler/Period are programmed as N-1
Is you system really clocking at 82 MHz?
Each timer has a single counting element, and a single period. The CCRx setting can fire at different phased of the counter.
Why do you need so many timers? Can you not establish a time base, and the queue events against that, or decimate.
As dhenry indicates you could program one of the 32-bit counters in a freerun/maximal mode, this establishes a timebase in CNT, and you can place events in CCR1, CCR2, etc along that timeline, and interrupt.
2018-06-22 05:49 AM
'
but do not know how to set what you mentioned.
especial to HAL API?'
I don't work with hal so you will just need to figure out how to implement those steps in hal. like:
1) set up a free-run timer in hal: can you do that?
2) set up compare point in hal;
3) enable compare interrupt in hal?
4) write compare ISR?
5) read timer counter in hal?
...
at some point, you have to help you help yourself.
2018-06-22 05:58 AM
dear Eklin and Clive:
yes, I have to use timer interrupts for some time sensitive modules(tasks) inside the interrupt routine, the current tasks' levels(main loop without OS), some tasks take too long, and make other tasks, which need to process some data in exactly time, miss executions and results are bad. this is one reason, another reason, in the task level, it is related to communication with outside interface, we have to use timer to avoid waiting time out, there are other reasons.
this is micro controller which handle 3 hardware serial interfaces to communication outside, and adc and dac interface involved and some math calculation. I have to weight all the tasks and interrupt routines...
2018-06-22 05:59 AM
Dear Dhenry:
thanks, I will read your codes in more details.
thanks
2018-06-22 11:34 AM
Dear Eklin:
thanks for your reply.
So far I do not have problems to set most interrupts and balance between tasks level and interrupt. The balances among interrupt latency and context switch are all very good so far which really solve our purely poll 's structure . HAL api gives very good interrupts' flag cleaning and setting . The only problem is limit timers I could use. So now I have to utilize multiple channels for each timer . I am still reading Mr. Dhenry's examples to know how to use HAL's API to set each channel of one timer .
since we also have ADC interface, if I could use ADC interrupt for its timing, I may not need to use so many timer's interrupts.
will let you know how about my progress.
thanks
roseanne
2018-06-22 12:06 PM
Hi
roseanne.qiu461
, based in the needes I would suggest to you the following if you are using HAL and CubeMX:* Define in your program the periods that need to be counting at same time, I´m quite sure that there are instants where all 8 timers don't need to be counting at same time.
* Set all the timers with an initial period, enable all interruptions, set all in freerun mode, be sure that preescaler value is able to handle required times, and set different priorities for each timer.
* As programming
recommendation
, set macros to enable and disable interrupts, start and stop timers and change counting periods, there is an example of one code I made:* In the main loop set the periods and the timers in the moment that are needed, enable the timers interrupts and start the counting.
* Using the HAL you must to take on count that there is just one function to handle all timers callbacks, so you must to check from which timer comes the interrruption with some like this:
* You should disable some interruptions to avoid that could be called meanwhile the interruption function is in execution.
* In order to check not only from which timer come the interrupt, you should declare a global flag to know which task is in execution (In the case that you are setting a timer with different periods).
* Don't make long codes in the callback function, instead set or clear flags that could be related in the main loop, I suggest to do the main loop as a state machine, if you make the state machine diagram of all your code you could see clearly where you have to set and start the timers.
Not sure if that could help to you, but works for me. Thanks
2018-06-22 01:41 PM
Dear Elkin and Dhenry:
I used the similar function you gave for Hal callback function for timer update(expire), I do not have the problem so far
I am struggling to try to use multiple channels of one timerf
I read back HAL lib:
void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)
{ /* Capture compare 1 event */ if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1) != RESET) { if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC1) !=RESET) { { __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1); htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1; /* Input capture event */ if((htim->Instance->CCMR1 & TIM_CCMR1_CC1S) != 0x00U) { HAL_TIM_IC_CaptureCallback(htim); <===========I believe in my case I do not use this one for multiple channels of one time } /* Output compare event */ else { HAL_TIM_OC_DelayElapsedCallback(htim); <==========I believe in my case, I need to use this one for multiplechannels of one timer
HAL_TIM_PWM_PulseFinishedCallback(htim); <==========I believe in my case I do not use this one } htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED; } } }.....
/* TIM Update event */ if(__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET) { if(__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_UPDATE) !=RESET) { __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE); HAL_TIM_PeriodElapsedCallback(htim); <--------------this is regular interrupt I am using now , to multiple channels ofone timer, I do not think that I need to use this one.
} }....
=======================================================
so if I am correct, I will use
HAL_TIM_OC_Start_IT(&Tim3Handle, TIM_CHANNEL_1); <==========enable channel 1 interrupt of timer 3
HAL_TIM_OC_Start_IT(&Tim3Handle, TIM_CHANNEL_2);<============enable channel 2 interrupt of timer 3 HAL_TIM_Base_Start_IT(&Tim3Handle); <===========I do not need to use this one for channel interrupt, this is onlyused for a timer expire, not for their channel
by reading from your codes, it seems that
every time , once interrupt happen for a channels , I need to update output compare register count inside compare interrupt of
HAL_TIM_OC_DelayElapsedCallback(htim);, but if compare register's data is over flow, I may need to reset the data again.
I am still trying to test this, if I am wrong, please let me know.
thanks for your help
thanks
rose
2018-06-22 06:37 PM
'
by reading from your codes, it seems that
every time , once interrupt happen for a channels , I need to update output compare register count inside compare interrupt
'
I said as much, plainly,
you have two choices:
1. take my code / structure and implement it with HAL-equivalents;
2) take my code, include it in your code and hit the compile button and it will just work - with minimum changes if you are on a different chip.
once the code is up and running, using it is easy:
tim1_init(1); //initialize tim1 as 1:1 prescaler
tim1_setpr1(1000); //set channel 1 period to 1000x1 ticks;
tim1_act1(task1); //user handler, task1(), is invoked every 1000x1 ticks;
tim1_setpr3(20000); //set channel 3 period to 20000x1 ticks;
tim1_act3(task2); //user handler, task2(), is invoked every 20000x1 ticks
...
that's all there is.