2014-01-27 02:46 AM
Hey at all,
First of all I want to say that my english isn't the best. I have got a new project to do it on a STM32F405 controller. I must measure two frequencies: 1. f1 = 13 to 16MHz 2. f2 = 10 to 13MHz my plan to do it is: - create a internal time base 0.1ms - count at two input pins the edge of the two external frequencies, - and calculate it. So what is the best way to do it on STM32? I read something with master and slave timers. ?!? Further I want to do it in the peripherals to hold the cpu work very low. the next step is to save the calculated frequencies in two ring buffers. because i have to make a filter over some samples to get the correct value. what ist the best way to implement a ring buffer? I hope somebody can give me some tips, especially for the different timers. BR michael.2014-02-05 02:48 AM
At the moment I can count the external pulses. And calculate the Frequency of the external Signal. But I do this at the moment with Interrupts of my TimeBase generator.
And thats happens every 100µs. :\ What I want to realize next is following: check the frequency with my existing timebase. if the frequency is = 1MHz don't save the values and don't interrupt the main program. if the frequency is = 2MHz or higher!! start saving the values still the frequency drops down to 1MHz. my approach is: to generate the timebase of 0.1ms. (Timer1) reset after every UEV the Timer2 compare register. counts the external pulses. with two compare registers (Timer2) compare1 value = 200 (2MHz) (2MHz/10kHz) how I can realize to compare the compare1-value with the counter of the external pulses?? if compare1 reaches the value save the compare2-value every 0.1ms in the ring buffer. is it possible to do this with one Timer? It doesn't matter if the main programm is interrupted while the frequency is > 2MHz. BR M.2014-02-07 01:34 AM
hey...
my problem is: the master timer resets the slave timer every update event. And I want to read the counter value from the slave timer every update event of the master timer. But the slave counter value is 0 if I want to read it. Masters TRGO is Update. and Slaves TRGI is Reset-Mode. Can I switch off and on the Master/Slave mode during operation by software in an InterruptHandler? Thanks M.2014-02-07 02:05 AM
Hi
''Can I switch off and on the Master/Slave mode during operation by software in an InterruptHandler?'' Yes. Why are you slaving one timer to the other? From what I understand you are trying to do: You simply need one timer to generate a regular interval (ie period) and this generates an IRQ. The ISR for this will measure the frequency by checking a count of another timer. Then it can zero the count. The other timer should be set up to just count from the external pin.2014-02-07 03:17 AM
I don't want to be interrupted every 0.1ms.
But if the frequency increases it is okay if the program is interrupted! the frequency increases only about for max. 100ms. after this time i have to make some calculations with the values! and there it would be a problem if i become interrupted every 0.1ms, i think. i am going to post my code, if you find a mistake please help me'!!2014-02-07 03:22 AM
static void TIM2_Time_Base(void)
{
static unsigned short frequency = 0, PSC = 0;
static unsigned long ARR = 0;
// calculate ARR and PSC by given frequency
frequency = 10000; // 1kHz
PSC = 0;
ARR = (84000000 / frequency) - 1;
//TIM2 Clock Enable
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
//Time Base Configuration
TIM_TimeBaseStructure.TIM_Period = ARR; // use calculated Autoreload value
TIM_TimeBaseStructure.TIM_Prescaler = PSC; // use calculated Prescale value
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = ARR;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Disable);
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
// Interrupt UpdateEvent in Capture 2 Register Timer2
TIM_ITConfig(TIM2, TIM_IT_CC2, DISABLE);
//Master Mode for Tim2
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
// Enable the MasterSlave Mode
TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);
//Timer enable
TIM_Cmd(TIM2, ENABLE);
}
static void TIM3_etr_cnt(void)
{
//TIM3 Clock Enable
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// Time Base Configuration
TIM_TimeBaseStructure.TIM_Period = 65535;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
// configure external clock mode 2
TIM_ETRClockMode2Config(TIM3, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 80;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Disable);
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
// Enable Interrupt for TIM3 Capture 2
TIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE);
// Slave Reset-Mode for TIM3 ITR1
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
TIM_SelectInputTrigger(TIM3, TIM_TS_ITR1);
// Enable Timer 3
TIM_Cmd(TIM3, ENABLE);
}
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)
{
// Clear TIM2 Capture Compare2 interrupt pending bit
TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
TIM_ITConfig(TIM3, TIM_IT_CC2, DISABLE);
TIM_Cmd(TIM3, DISABLE);
// get counter value TIM3
tim3_counter = TIM_GetCounter(TIM3);
//set flag state to 1 to compare it in main
flag = 1;
// set counter value TIM3 equal 0
TIM_SetCounter(TIM3, 0);
//Start Timer and Counter
TIM_Cmd(TIM3, ENABLE);
}
}//TIM2_IRQHandler
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)
{
//Clear TIM3 Capture Compare1 interrupt pending bit
TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
// Disable Interrupt for TIM3 Capture 2
TIM_ITConfig(TIM3, TIM_IT_CC2, DISABLE);
// Disable the MasterSlave Mode
TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Disable);
TIM_Cmd(TIM3, DISABLE);
TIM_Cmd(TIM2, DISABLE);
// set counter value 0
TIM_SetCounter(TIM3, 0);
TIM_SetCounter(TIM2, 0);
// Enable Interrupt UpdateEvent in Capture 2 Register Timer2
TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);
//Start Timer and Counter
TIM_Cmd(TIM3, ENABLE);
TIM_Cmd(TIM2, ENABLE);
}
}//TIM3_IRQHandler
for(;;)
{
if(flag == 1)
{
buffer2[i] = tim3_counter;
i++;
flag = 0;
if(i == 100)
{
TIM_Cmd(TIM3, DISABLE);
TIM_Cmd(TIM2, DISABLE);
TIM_ITConfig(TIM2, TIM_IT_CC2, DISABLE);
TIM_SetCounter(TIM2, 0);
TIM_SetCounter(TIM3, 0);
// Enable the MasterSlave Mode
TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);
// Enable Interrupt for TIM3 Capture 2
TIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE);
TIM_Cmd(TIM3, ENABLE);
TIM_Cmd(TIM2, ENABLE);
i=0;
}
}
} //for
2014-02-07 03:32 AM
Hi
''I don't want to be interrupted every 0.1ms.'' OK then. Slave 1 timer to the other. The slave timer still want to be a counter driven by external source. The slave timer now has to be in Compare Mode (I think it is compare). In this mode, when the count reaches/matches the number in CCRx register - it generates an event. The event can trigger an IRQ. The value in CCRx is the same as the ARR value for master timer. The ISR needs to look at the Master timer count and work out the proportion of master count to slave count (master count will be smaller when the slave source is faster than master timer). Please read the timer section(s) of the reference manual. There are multiple sections because it depends on which timer is being used. ''i am going to post my code, if you find a mistake please help me'!!'' I do not have the time to debug your code - you are going to have to do that yourself. I can help you by giving you advice or guidance.2014-02-10 04:26 AM
hey,
I came to the result, that it isn't possible to disable the MasterMode via ''TIM_SelectMasterSlaveMode(TIMx, TIM_MasterSlaveMode_Disable)'' in an interrupt routine. At the moment I use TIM_DeInit and configure the timer again and it is working! Do you know some existing problems with the Disable-Function? or is it possible, that i still use it wrong? Thanks, M.2014-02-10 09:57 AM
Hi
I am lost now with what you are doing and how you are doing it. ''I came to the result, that it isn't possible to disable the MasterMode via ''TIM_SelectMasterSlaveMode(TIMx, TIM_MasterSlaveMode_Disable)'' in an interrupt routine.'' ''Do you know some existing problems with the Disable-Function? or is it possible, that i still use it wrong?'' Well, the code is doing a read, modify, write - which is suppose to be a bad thing when accessing certain registers! (Just goes to show - even supplied 'library' code is not perfect.) I am not sure this is the cause of your issue, you would have to codify the code and see if it works in the ISR. The registers themselves are defined as volatile - which tells the compiler that the value may change at run time - so do not assume the value is the same as when it was last accessed, always read the value from memory.