2017-05-18 01:46 PM
Hi.
I'm trying to use TIM1's channel 1 as a spindle RPM input capture. ( device is STM32F103C8 )
Knowing that the spindle has a single pulse per revolution and is rated from 0 to 30K rpm, the frequency domain is 0 to 500Hz. Easy feat for a timer running at 48MHz.So I configured TIM1's prescaler to 480, its period to 0xFFFF, direct input, no prescaling nor filtering (sharp input signal)...
So far so good, frequencies from 5Hz to 1KHz are registering nicely...But here's my issue : I was planning to count the number of UPDATE interrupts to detemine when the signal's period dropped too much ( i.e. the spindle was idling ).
BUT : it seems that I'm missing some UP events. The update interrupt isn't always firing.
Here's my code. The first method is CubeMX's output./* TIM1 init function */static void MX_TIM1_Init(void){TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig; TIM_IC_InitTypeDef sConfigIC;htim1.Instance = TIM1;
htim1.Init.Prescaler = 512; htim1.Init.CounterMode = TIM_COUNTERMODE_UP; htim1.Init.Period = 0xFFFF; htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim1.Init.RepetitionCounter = 0; if (HAL_TIM_Base_Init(&htim1) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); }sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); }if (HAL_TIM_IC_Init(&htim1) != HAL_OK)
{ _Error_Handler(__FILE__, __LINE__); }sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); }sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI; sConfigIC.ICPrescaler = TIM_ICPSC_DIV1; sConfigIC.ICFilter = 0; if (HAL_TIM_IC_ConfigChannel(&htim1, &sConfigIC, TIM_CHANNEL_1) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); }}
// Some global variables
volatile bool _toolRawRevValid;
volatile uint32_t _lastTim1CC,_toolRawRev, _tim1Ovf ;void InitializeInputStage(void){ // prepare variables_toolRawRev = 0;
_toolRawRevValid = false; _tim1Ovf = 0; _lastTim1CC = 0; // Start TIM1 and its interrupts (as configured in MX_TIM1_Init() ). HAL_TIM_Base_Start_IT(&htim1); // start counting, enable UPDATE interrupt HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1); // enable IC interrupt (already counting now).}// Auto-reload (update) event interrupt handler
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{ if(htim == &htim1) { _tim1Ovf++; // count roll-overs. if(_tim1Ovf >= 2) _toolRawRevValid = false; }}// Timers Capture handler
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{ register uint32_t currCap, ovf, tc; if(htim == &htim1){ currCap = HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_1); tc = TIM1->CNT; ovf = _tim1Ovf; // number of TIM1-CNT rollovers _tim1Ovf = 0; if(currCap <= _lastTim1CC) { if(!ovf){ // no roll-over occured ? while(1) __NOP; // the previously captured value is higher than the current one, but no timer overflow registered ? } _toolRawRev = ((TIM1->ARR * ovf) + currCap )-_lastTim1CC; }else{ _toolRawRev = (TIM1->ARR * ovf) + (currCap - _lastTim1CC); } _toolRawRevValid = true; _lastTim1CC = currCap; } }So here's the strange fact : my program keeps hitting the __NOP statement in the HAL_TIM_IC_CaptureCallback(...) method.
Is Timer1 gated by its input capture somehow ?PS: sorry for the repetitive edits, I'm discovering the community's new interface. =/
#stm32f1 #isr #missing #input-capture #interrupt2017-05-19 04:46 AM
Does the update interrupt fire at all?
TIM1 in many STM32 has separate interrupts for the update and for CC. If your STM32 model has it so, does it have both enabled in NVIC and directed properly towards the Cube mess? (I don't Cube so don't know how to do that).
[
Yes, I know I re-asked the same question. No, you don't prove update interrupts being fired by update, just by placing a breakpoint in the callback - the callback will get called back from a different interrupt.
If I am right in this, this is a deserved punishment for using a 'library'.
]
JW
2017-05-19 07:07 AM
Using a data watchpoint at run-time ?
Nice out-of-the-box thinking !2017-05-19 07:13 AM
Right now, I'm with you on this.
Although each interrupt vector (UP and CC) only call one MX method, there's too much mess in those (and conditionals statements) to call it clear code. There's too much symbols hiding simple registers affectations while others refer to full-fledged subroutines.I've joined the Cube bandwagon since it was an 'up-to-date' version of ST's framework, but their abstraction layer is either too abstracted or not enough. And very poorly documented at that.I'll switch back to direct register manipulation for this. Gain of both clarity and code size (although small).2017-05-20 06:10 AM
Gosh, I'm so upset and ashamed of myself.
Turns out the culprit was the function generator I used on my test bench.This horrible piece of chinesium won't output anything at 4hz, and creates high-piched harmonics at very low frequencies, around 1Hz and 2Hz.But its signal is clean and spotless above 5Hz !The code was functional all along -_-.
Anayway, thanks you guys for your interest and support !Guess I'll have to buy a new signal generator =/
2018-05-12 08:35 AM
Dear Jla
I have produced a small tutorial based on the application note AN2592 'Achieving 32 bit timer resolution with software expansion for STM32Cube'. I used a STM32L053 MCU which does not own any 32 bit timer or DWT cycle counter.
May I expect that it will be useful for you. Do not hesitate to give me back your feel back.
Sincerely yours
JC Toussaint
2018-05-12 10:43 AM
Easy.
1. Enable the time base overflow interrupt and
2. In its isr, increment a counter. If you pick that counter to be a 32 bit type. To gather with a 16 bit timer counter you have a 48bit timer.
You can then detect 0 frequency in the isr.
2018-05-12 12:47 PM
You can simply config one of pwm channels to generate something like that. That way you know for sure what signal you should expect.