STM32 32 bit chain timer missing MSB - Page 1
Forum section: electronics / general

author: rvalente
author_rank: Frequent Contributor
timestamp: October 28, 2018, 10:00:20 pm
content: Dear mates,I`m using a STM32F103C8T6 (bluepill board) for two input capture (frequency meter), for 4 to 600Hz, square wave from a VR sensor.I chained TIM3 as master to TIM2 as slave, used ST AN2592 as guidehttps://www.st.com/resource/en/application_note/cd00165509.pdfThe frequency is being fed to CH1 and CH2 of both timers, so I`m feeding the signal in two IO pins per channel.Used STM32CubeMX for configs, and Atollic as IDE.TIM3 and TIM2 is configured this way:Basically, whenever I have a input capture interruption, I read tim2 channel and tim3 channel (wherever channel 1 or 2, depends on the interrupt) as two 16 bit and assemble them as 32 bit. Doing that twice I get the frequency period and the frequency is them 10MHz(APB1 Timer clock)/frequency period.It works like a charm for capturing two channels but, every 5s or so a glitch happen in the capture (both channels). The glitch is the delta capture (second capture minus the first) is around 65536. So, the TIM2 (slave) sometimes is counting one unit plus and others one unit less.Attached, a small sample from STM Studio (the signal is capture delta).Am I missing any thing to correctly chain this timers?Greetings!

author: bson
author_rank: Unknown
timestamp: October 28, 2018, 10:40:39 pm
content: Are you sure the lower half timer isn't simply rolling over between the two 16 bit reads?Since you're not ticking at very high frequencies you might be able to read timer H, then L, then H again, repeating this song and dance until the two H readings match, indicating there was no rollover.

author: newbrain
author_rank: Super Contributor
timestamp: October 28, 2018, 11:12:35 pm
content: Quote from: rvalente on October 28, 2018, 10:00:20 pmAre you sure you followed all the indications in the AN?The description there is frankly confusing, partly contradictory, and the formulae look fishy...Though, from the pictures you attached I noticed the following differences:The Master Slave Mode bit (MSM) is not set, the AN states: "Enable the Master/Slave mode."TIM2 slave mode is set to "Trigger Mode", the AN states: "Use the external clock mode 1 as the Slave mode" - with this mode, the prescaler should be set to 0, not to 0xFFFFExplanation:The MSM bit will make sure the clocks are correctly synchronized in a master slave configurationUsing the external clock mode, TIM2 will step once every time the TIM3 rolls over, with your setting of "Trigger Mode" TIM" will simply be started when TIM3 rolls over (so, quite the same thing with a 216prescaling, but not exactly...)

author: rvalente
author_rank: Frequent Contributor
timestamp: October 29, 2018, 12:09:06 pm
content: Quote from: bson on October 28, 2018, 10:40:39 pmI dont think the problem is the rollover, I`m reading the capture registers, not the timer. As soon the timer 2 and 3 pins goes from low to high, the capture register latchs the timer value, freezing it. Right?

author: rvalente
author_rank: Frequent Contributor
timestamp: October 29, 2018, 12:22:30 pm
content: Quote from: newbrain on October 28, 2018, 11:12:35 pmI do not followed every step as AN stated, found the AN confusing ans well (the provided code diverges from the AN).I changed the TIM3 to not to reset mode, since I`m using 2 channels capture, it will bother me.The TIM3 slave mode is not set (pinout window) and in the configuration window, the TRGO enabled ou disabled makes no difference.As you are explain-me I believe my timers were not chained, but the TIM2 is used in prescaller mode, counting 2^16 less them the TIM3.So, I followed your suggestions, the TIM2 is prescalled to zero, tim3 TRGO enabled, update event, TIM2 slave mode as external clock mode 1.The glitches behave much much better now, but from time to time I still can see a small glitch couting up (as the TIM2 is couting twice).

author: newbrain
author_rank: Super Contributor
timestamp: October 29, 2018, 08:28:03 pm
content: I see the error looks now 32768 (well, around 33000...), it would seem strange that this is caused by the HW capture.Could you check the correctness of the code for reassembling the 32bit values from the 16bit ones (or post it here!)?I would rather suspect some unsigned vs signed mishap.If I have time later tonight, I might even try to reproduce your configuration...

author: rvalente
author_rank: Frequent Contributor
timestamp: October 30, 2018, 12:41:57 am
content: Quote from: newbrain on October 29, 2018, 08:28:03 pmThanks by helping me, this is driving me nuts...The file tim.c was generated by cube32mx, has tem the TIM2 and TIM3 init.The main.c, I was obliged to add the tim3 init call, I don't know why cube generated the TIM3 init, but did no called it on main.Also, i did add the Input capture enable and start (lines 113 to 123 of main.c)The file IO.c, there is a function call captureInputCompare, this function is called by TIM3_IRQHandler from the stm32fxxx_it.c (also generated by cubemx).On captureInputCompare I did some tests, but basically was reading the two input captures through __HAL_TIM_GET_COMPARE, shifting the htim2 (msb) << 16 and OR (||) to tim3, in 32 bit integer, thats all.Thanks by your help!!!

author: newbrain
author_rank: Super Contributor
timestamp: October 31, 2018, 08:48:57 am
content: Quite a lot of code!Sorry, I did not have much time to go through it (I probably was not clear, I expected a code snippet, not the whole shebang), and to experiment/read until yesterday nightNow, since you you showed me yours, I'll show you mine: it's a bit shorter, but works as intendedCode:static volatile uint32_t oldCapture = 0;static volatile uint32_t period = 0;static volatile bool captured = false;void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){uint16_t newLSB = TIM3->CCR1;uint16_t newMSB = TIM2->CCR1;uint32_t newCapture = (newMSB << 16) | newLSB;period = newCapture - oldCapture;oldCapture = newCapture; // Save the last captured valuecaptured = true; // Signal main loop}Now some explanations and comments:I used another timer to generate a jittered signal, the captured periods were always correct (in the jitter boundaries), I tried with many different ones with and without "carry" to TIM2.I see you are calling your own routine from the TIM3 ISR, I instead used the callback facility provided by the HAL: just declare a function with the right name and it will be used (instead of the default, empty,weakone)There's no reason CubeMX should not generate the right inits, it's more or less the only good thing going for it. Now I see it: you just forgot to check "Internal Clock" on TIM3!You don't need to enable interrupt manually with__HAL_TIM_ENABLE_IT(), that's taken care of by the HAL withHAL_TIM_IC_Start_IT().There's no need to enable interrupts on TIM2: the TIM3 interrupt will take care of both captures: AFAICS, you did not add any code, but the HAL basic ISR overhead is already quite high, and that will be called as you usedHAL_TIM_IC_Start_IT().If you are capturing at the maximum possible rate in STMStudio, bad things will happen: check the capture properties and set a sane sampling rate, I used a couple of ms; the check for correct capture values was in the code.I was not able to make the TIM3 auto reset (as suggested in the AN) work reliably when using a master slave configuration: probably the HAL ISR overhead is too high, but I did not investigate further (since you are not using it). It works with a single timer, though.Check carefully yourcaptureInputCompare()function, I see duplicate lines, and checking CC2 flags, then clearing CC1 ones. Of course, all this flag checking and clearing is not needed if you rely on the HAL callbacks.You used a two step approach to calculating the period, I just store the new reading in the old one after calculation (no need for additional state and if, to the cost of a borked initial reading).Also, make sure that the Systick ISR (and other interrupts you might be using) is always shorter than the period to be measured, or, alternatively, define a clear interrupt priority hierarchy.HTH