Macro USEC_TO_COUNT not working correctly

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Macro USEC_TO_COUNT not working correctly

Jump to solution
1,325 Views
josecarlos
Contributor II

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:

  •   TPM0 is use to control a buzzer. Configuration is shown below
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 is configured as systick, every 100ms. Configuration is shown below
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);‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
  • TPM2 is configure as Timer, it should interrupt every 100ms.
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);‍‍‍‍‍‍‍‍‍‍‍‍‍
  • Handler of TMP2
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);
}

      

  • remMiliseconds is a uint16_t and seted in runtime with buttons that increment and decrement the value of the variable
  • input_delay is a float that hold the value of an specific delay. So, if I set a 1.2s input_delay, remMiliseconds is equal to 1200 miliseconds.
  • Clocks are config as follow:

clocks.PNG

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.

Labels (1)
1 Solution
1,174 Views
mjbcswitzerland
Specialist V

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

View solution in original post

4 Replies
1,175 Views
mjbcswitzerland
Specialist V

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

1,174 Views
josecarlos
Contributor II

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.

0 Kudos
1,174 Views
mjbcswitzerland
Specialist V

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

0 Kudos
1,174 Views
josecarlos
Contributor II

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

0 Kudos