2016-02-16 03:15 PM
Hi,
On this link there's an example piece of code: https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a%2f%2fmy.st.com%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex_mx_stm32%2fMultiple%20PWM%20input%20capture%20on%20one%20timer&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A7... Hoping someone could clarify a few things. In the example posted above, it uses TIM2 over 4 channels to measure 4 signals. It is configured to use PD3,PD4,PD6,PD7. I do not see in the documentation where those pins can be used as an alternate function on TIM2. Can you explain that please? Secondly, if I wanted to measure at least 2 frequencies as configured in this example, do they need to be the same but differ only in phase? Can they be different frequencies - but within the range of the configuration? I need to measure 2 different signals. For example, I'm using PA.5 on TIM2. When I run the code it works fine and measures the signal's frequency. Following the above example, I've tried adding PA.6 in the same way. The interrupt handler is configured for both TIM_IT_CC1, and TIM_IT_CC2. But, with a signal applied to PA.6, there is nothing happening. Code is below. Can someone explain why it does not work? //set up to capture pulses on PA5, PA6 void TIM2_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; /* TIM2 Periph clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); /* TIM2 GPIO clock enable */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); /* TIM2 pin PA5, PA6 configuration */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Connect TIM2 pins to AF2 */ GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_TIM2); GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_TIM2); /* Time base configuration */ TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_Period = (uint32_t)0xFFFFFFFF; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising | TIM_ICPolarity_Falling; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter = 0; TIM_ICInit(TIM2, &TIM_ICInitStructure); TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising | TIM_ICPolarity_Falling; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter = 0; TIM_ICInit(TIM2, &TIM_ICInitStructure); //Set up TIM2 interrrupt NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* TIM enable counter */ TIM_Cmd(TIM2, ENABLE); /* Enable the CC2 Interrupt Request */ TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE); TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE); TIM_ClearFlag(TIM2, TIM_FLAG_CC1 | TIM_FLAG_CC2); } #cc2 #stm32f4 #tim2 #cc12016-02-16 07:41 PM
His target hardware was an STM32F3-DISCO with an STM32F303VC
http://www.st.com/web/en/resource/technical/document/datasheet/DM00058181.pdf
You are time stamping edges in the time domain of TIM2, the frequencies of the signals you are measuring can be different. The delta measurement allows you to determine the period in ticks of the TIM2 clock. The upper end of the frequency will be limited by the resolution/granularity of the timer, and the synchronization circuit on the input (think nyquist and aliasing).2016-02-16 07:51 PM
hmmm...I don't understand. Not sure what nyquist has to do with this. The frequencies are within a handful of Hz (as in under 20)
With that in mind, as I asked - what's wrong with the code I have posted - should it work, or am I missing something? thanks...2016-02-16 08:30 PM
I don't see it measuring anything, and
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising | TIM_ICPolarity_Falling;doesn't do what you want. You'd presumably want TIM_ICPolarity_BothEdge if you want to time stamp both the rising and falling edges.2016-02-16 08:44 PM
sorry, I still do not understand what you are saying.
Maybe I didn't make it clear. All I am trying to do on CC2 is the same thing I am doing on CC1, both using TIM2. Here is the interrupt code I have that toggles the LED on CC1. I am trying to figure out why I do not get an LED toggle on CC2. Yes, the code isn't the same as CC1, and no code to actuially do anything with the CC2 value, but right now I am just trying to get the LED to toggle, and it is not even doing that. I can apply a signal of 500Hz to PA5, and LED4 toggles. I then remove the signal and apply it to PA6, and LED6 does not toggle. So what is it...the setup? the interrupt? I must be really missing something obvious. //Timer 2 __IO uint32_t uhIC3ReadValue1 = 0; __IO uint32_t uhIC3ReadValue2 = 0; __IO uint32_t uhCaptureNumber = 0; __IO uint32_t uwCapture = 0; __IO float32_t uwTIM1Freq = 0; uint32_t TIM2_INT_RATE = (168000000 / 2); void TIM2_IRQHandler(void) { if(TIM_GetITStatus(TIM2, TIM_IT_CC1) == SET) { /* Clear TIM1 Capture compare interrupt pending bit */ TIM_ClearITPendingBit(TIM2, TIM_IT_CC1); if(uhCaptureNumber == 0) { /* Get the Input Capture value */ uhIC3ReadValue1 = TIM_GetCapture1(TIM2); uhCaptureNumber = 1; } else if(uhCaptureNumber == 1) { /* Get the Input Capture value */ uhIC3ReadValue2 = TIM_GetCapture1(TIM2); /* Capture computation */ if (uhIC3ReadValue2 > uhIC3ReadValue1) { uwCapture = (uhIC3ReadValue2 - uhIC3ReadValue1); } else if (uhIC3ReadValue2 < uhIC3ReadValue1) { uwCapture = ((0xFFFF - uhIC3ReadValue1) + uhIC3ReadValue2); } else { uwCapture = 0; } /* Frequency computation */ uwTIM1Freq = (float32_t) ((TIM2_INT_RATE/1.0) / (uwCapture/1.0)); STM_EVAL_LEDToggle(LED4); uhCaptureNumber = 0; } } else if(TIM_GetITStatus(TIM2, TIM_IT_CC2) == SET) { /* Clear TIM2 Capture compare interrupt pending bit */ TIM_ClearITPendingBit(TIM2, TIM_IT_CC2); TIM_GetCapture2(TIM2); STM_EVAL_LEDToggle(LED6); } }2016-02-16 08:50 PM
Nyquist, think about what happens if you gate a 15MHz signal through a 20MHz synchronizer.
Clearly it's not going to be a problem if the synchronizer is running several orders of magnitude above the signal being resampled, but I'm just covering my bases.2016-02-16 08:56 PM
It's a 32-bit timer, it doesn't wrap at 0xFFFF, and for that matter the 16-bit would wrap at 0x10000. This is broken code from the SPL examples.
Where uint32_t a, b, delta;delta = b - a; // for ALL uint32_t valuesWhere you are time-stamping 3 consecutive edges, A, B, CPeriod = C - A; // in ticks of the clockFirstHalfTime = B - A;SecondHalfTime = C - B;2016-02-16 09:19 PM
nope, not broken at all.
the code for CC1 works fine, and measures frequencies with better than 0.5Hz resolution. not sure what you aren't saying, but thanks. i think I'll try to figure it out in some other way...2016-02-17 05:55 AM
You really need to work through the math here, do it first with 16-bit unsigned math, and then 32-bit unsigned math.
/* Capture computation */
if (uhIC3ReadValue2 > uhIC3ReadValue1)
{
uwCapture = (uhIC3ReadValue2 - uhIC3ReadValue1);
}
else if (uhIC3ReadValue2 < uhIC3ReadValue1)
{
uwCapture = ((0xFFFF - uhIC3ReadValue1) + uhIC3ReadValue2);
}
2016-02-17 10:10 AM
you referring to the 0xFFFF ? I changed it to 32 bit and it makes no difference. Everything's declared as 32 bit, so what's the problem? It's a 32 bit counter.
clive1, why don't you try the code and discover that it does work? In fact it is precise to 0.1Hz. Anyhow, isn't this off topic? I wasn't asking for an inquisition into my frequency calculation. There is no issue with that because it does work well. All I am asking is, how can I read 2 differing signals, very close in frequency, on 2 different pins, using a single 32 bit timer, such as TIM2? Is that possible, or not? Is the code I posted to set up the timer close, or what's wrong with it? Thank you for helping to answer this question (or anyone else that wants to weigh in and help)