Hi everyone,
I'm having problems with TPM timers and USEC_TO_COUNT macro.
Context:
I'm using a KL17 as MCU an I'm working in an application in which I need a systick every 100ms and different timers to control specific processes. One of them is to control the opening of an electrovalve when an ultrasonic sensor detect an object, if a delay time is configured, the electrovalve should open at object detection and delay time have finished. So, now I'm using 1 TPM as PWM and 1 TPM as Timer and also I'm using PIT as follow:
tpm_config_t tpmConfig;
tpm_chnl_pwm_signal_param_t pwmChannelParam;
TPM_GetDefaultConfig(&tpmConfig);
TPM_Init(TPM0, &tpmConfig);
pwmChannelParam.chnlNumber = kTPM_Chnl_2;
pwmChannelParam.level = kTPM_HighTrue;
pwmChannelParam.dutyCyclePercent = 0;
TPM_SetupPwm(TPM0, &pwmChannelParam, 1U, kTPM_EdgeAlignedPwm, 2000U,
CLOCK_GetFreq(kCLOCK_McgIrc48MClk)/4);
TPM_StartTimer(TPM0, kTPM_SystemClock);
pit_config_t pitConfig;
PIT_GetDefaultConfig(&pitConfig);
/* Init pit module */
PIT_Init(PIT, &pitConfig);
uint32_t freq = CLOCK_GetFreq(kCLOCK_McgInternalRefClk);
/* Set timer period for channel 1 */
PIT_SetTimerPeriod(PIT, kPIT_Chnl_1, USEC_TO_COUNT(100000U, CLOCK_GetFreq(kCLOCK_BusClk)));
/* Enable timer interrupts for channel 1 */
PIT_EnableInterrupts(PIT, kPIT_Chnl_1, kPIT_TimerInterruptEnable);
/* Enable at the NVIC */
EnableIRQ(PIT_IRQn);
tpm_config_t timerConfig;
TPM_GetDefaultConfig(&timerConfig);
TPM_Init(TPM2, &timerConfig);
uint32_t freq = CLOCK_GetFreq(kCLOCK_McgInternalRefClk);
TPM_SetTimerPeriod(TPM2, USEC_TO_COUNT(100000U, freq));
TPM_EnableInterrupts(TPM2, kTPM_TimeOverflowInterruptEnable);
EnableIRQ(TPM2_IRQn);
void TPM2_IRQHandler(void){
if (remMiliseconds == 0){
if (leftSonarLastState == CLOSE)
openElectrovalve(LEFT_ELECTROVALVE);
if (rightSonarLastState == CLOSE){
openElectrovalve(RIGHT_ELECTROVALVE);
}
remMiliseconds = (global_var.input_delay * 1000);
TPM_StopTimer(TPM2);
}else{
remMiliseconds -= 100;
}
TPM_ClearStatusFlags(TPM2, kTPM_TimeOverflowFlag);
}
Expected behaviour:
When use the buttons to increment or decrement the value of the delay, I'm setting the value of remMiliseconds. So, if I configured the TPM2 Timer to interrupt every 100ms and the value of remMiliseconds is 2000, the electrovalve should opens 2 seconds after the Timer had started.
Spected behaviour:
I set the value of input_delay to 2s, so the value of remMiliseconds is 2000 so the electrovalve should opens 2 seconds after the Timer had started but it opens at the time I start the timer. The timer start when I detect and object. So is like the timer is not interrupting as expected or maybe I didn't configured it correctly. I think also that the macro USEC_TO_COUNT is may not working fine.
Could someone here explain me, if the timer is configured correctly or what is wrong with my program logic?
Thank you and kind regards.
Solved! Go to Solution.
Hi
If you are clocking the TPM with 8MHz it will overflow every 8.19ms, which is its longest interrupt period. If you try to program it with longer values it will result in shorted ones (due to the overflow).
The TPM also has a pre-scaler that can increase the time delay up to x128, and so maximum 1.048s
- is the overflow the basic issue?
- do you see a compiler warning of an overflow at the macro?
Regards
Mark
Complete KL27 solutions, training and support:http://www.utasker.com/kinetis.html
Kinetis K27:
- http://www.utasker.com/kinetis/FRDM-KL27Z.html
- http://www.utasker.com/kinetis/Capuccino-KL27.html
Hi
If you are clocking the TPM with 8MHz it will overflow every 8.19ms, which is its longest interrupt period. If you try to program it with longer values it will result in shorted ones (due to the overflow).
The TPM also has a pre-scaler that can increase the time delay up to x128, and so maximum 1.048s
- is the overflow the basic issue?
- do you see a compiler warning of an overflow at the macro?
Regards
Mark
Complete KL27 solutions, training and support:http://www.utasker.com/kinetis.html
Kinetis K27:
- http://www.utasker.com/kinetis/FRDM-KL27Z.html
- http://www.utasker.com/kinetis/Capuccino-KL27.html
Hi Mark,
- is the overflow the basic issue?
Yes it is.
- do you see a compiler warning of an overflow at the macro?
No, the application compiles without warnings.
After answer your questions I want to thank you your help and explanation. It helps me a lot. I will apply the changed and report the results, feel free to stay in tune.
Kind regards.
Hi Jose
I would expect a warning on an overflow so it may be that the macro that is used is casting the result to a narrower storage value (which would not give a warning on overflow).
In such a case the macro would not correctly designed and may need a review.
Regards
Mark
Hi Mark
I'm glad to notice you that the timer is working perfectly. I configure it as shown below
tpm_config_t tpm2Config;
TPM_GetDefaultConfig(&tpm2Config);
tpm2Config.prescale = kTPM_Prescale_Divide_16;
TPM_Init(TPM2, &tpm2Config);
TPM_SetTimerPeriod(TPM2, USEC_TO_COUNT(100000U, CLOCK_GetFreq(kCLOCK_McgInternalRefClk)/16));
TPM_EnableInterrupts(TPM2, kTPM_TimeOverflowInterruptEnable);
EnableIRQ(TPM2_IRQn);
And is working as expected. Hope this new information would be useful. Thanks for your great support.
Regards,
Jose