STM32L timebetween pulses
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-09-06 6:35 AM
I'm trying to measure time between two pulses on a pin. Time between pulses is in 10 - 100 uS range so I can't use millis function. What I'm trying to do is use TIM2 CNT register. Since my APB2 clock is runnig at 32MHz I should get a resolution of about 0.03 uS.
The problem is that when I try to debug the CNT register is always at 0x0000 value :( I use this code to initialize timer: void Enable_Timer() { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_InitStructure.TIM_Period = 0xFFFFFFFF; TIM_InitStructure.TIM_Prescaler = 0x0000; TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_InitStructure); TIM_Cmd(TIM2, ENABLE); } And this to read the CNT value: tt= TIM_GetCounter(TIM2); EDIT: I am using STM32L152 board #timer #discovery #stm32l #tim- Labels:
-
TIM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-09-06 6:59 AM
The counters at all 16-bit as I recall, otherwise looks reasonable, so I'd question the context.
To measure pulses on a timer channel, you'd want to look at Input Capture mode.Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-09-09 6:47 AM
Tried input capture mode, but can't start the timers.
My Code:
GPIO pin initialization
/* Enable GPIOA clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
/* Enable SYSCFG clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_Pin_10, GPIO_AF_TIM2);
Enable Timer 2 and Interrupt on timer update:
void Enable_Timer()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_InitStructure.TIM_Period = 0xFFFFFFFF;
TIM_InitStructure.TIM_Prescaler = 0x0000;
TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1
TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_InitStructure);
TIM_Cmd(TIM2, ENABLE);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInitStructure.TIM_ICFilter = 0x00;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
}
Timer interrupt:
void TIM2_IRQhandler()
{
if (TIM2->SR & TIM_IT_CC2)
{ /* capture timer */
TIM2->SR = ~TIM_FLAG_CC2;
if(CaptureNumber == 0)
{
/* Get the Input Capture value */
IC2ReadValue1 = TIM2->CCR2;
CaptureNumber = 1;
}
else if(CaptureNumber == 1)
{
/* Get the Input Capture value */
IC2ReadValue2 = TIM2->CCR2;
/* Capture computation */
if (IC2ReadValue2 > IC2ReadValue1)
{
Capture = (IC2ReadValue2 - IC2ReadValue1);
}
else
{
Capture = ((IC2ReadValue2 + 0x10000) - IC2ReadValue1);
}
IC2ReadValue1 = IC2ReadValue2;
}
}
}
Still the Capture value doesn't change. Ant timer register value is always zero. I just can't figure out why it is not working.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-09-09 8:57 AM
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_TIM2);
TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-09-10 3:27 AM
Will I see timers running in debug window?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-09-10 8:12 AM
Dunno, the code is insufficiently complete for me to quickly test, and I don't know what tool chain/debugger you have.
Personally, I'd array the samples and break-point, and then look at the array, should be apparent if it's functional, or the measurements are within scope. Alternatively you could print results periodically to the USART.Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-09-11 6:26 AM
I have the timer running. But now I can't get an interrupt to measure pulse width on PB
If I set interrupt flag by software I get correct timer values. But I can't make a hardware interrupt. I think the problem is somewhere in void Enable_Timer() function, but I just can't find it :(
I'm using Keil. Here's the full code:
#include ''stm32l1xx.h''
#include ''stdio.h''
#include ''string.h''
#include ''math.h''
int Capture;
int CaptureNumber;
int IC2ReadValue1;
int IC2ReadValue2;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
TIM_TimeBaseInitTypeDef TIM_InitStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
//*****************************************************
//Enable system clocks for input configuration
//*****************************************************
void Enable_Clocks()
{
/* Enable GPIOA clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
/* Enable GPIOA clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
/* Enable SYSCFG clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
}
//******************************************************
//******************************************************
//TIM2 interrupt
//******************************************************
void TIM2_IRQhandler()
{
GPIO_ResetBits(GPIOB, GPIO_Pin_11);
if (TIM2->SR & TIM_IT_CC2)
{
TIM2->SR = ~TIM_FLAG_CC2;
if(CaptureNumber == 0)
{
/* Get the Input Capture value */
IC2ReadValue1 = TIM2->CCR2;
CaptureNumber = 1;
}
else if(CaptureNumber == 1)
{
/* Get the Input Capture value */
IC2ReadValue2 = TIM2->CCR2;
/* Capture computation */
if (IC2ReadValue2 > IC2ReadValue1)
{
Capture = (IC2ReadValue2 - IC2ReadValue1);
}
else
{
Capture = ((IC2ReadValue2 + 0x10000) - IC2ReadValue1);
}
IC2ReadValue1 = IC2ReadValue2;
}
}
}
//******************************************************
//******************************************************
//Enable APB pin 10 for timer interrupt input
//******************************************************
void Enable_APB()
{
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_TIM2);
}
//******************************************************
//******************************************************
//Enable TIM2 timer
//******************************************************
void Enable_Timer()
{
TIM_InitStructure.TIM_Period = 0xFFFF;
TIM_InitStructure.TIM_Prescaler = 32;
TIM_InitStructure.TIM_ClockDivision = 0;
TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_InitStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInitStructure.TIM_ICFilter = 0;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_TRC;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
TIM2->SMCR = 0x00000074;
TIM_SelectInputTrigger(TIM2, TIM_TS_ETRF);
TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);
TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
TIM_Cmd(TIM2, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);
}
//******************************************************
//******************************************************
//Main function calls all other functions when needed
//******************************************************
int main(void)
{
Enable_Clocks();
Enable_APB();
Enable_Timer();
/* Infinite loop */
while(1)
{
}
}
//******************************************************
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-09-11 7:00 AM
I'm confused,
You enable a bunch of clocks, USART2 twice, SYSCFG not at all. Things that aren't used and inconsistent with the comments. You use PB10, which as I recall is TIM2_CH3, you then make a bunch of reference to CH1 when configuring the TIM and interrupt, and then your interrupt code makes references to CH2 For a time base of 1 MHz from a 32 MHz core, then 32-1 for the prescalerUp vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-09-11 7:24 AM
Try this, it a blind build but is at least internally consistent.
#include ''stm32l1xx.h''
#include ''stdio.h''
#include ''string.h''
#include ''math.h''
volatile int Capture; // Changed under interrupt
volatile int CaptureCount = 0;
//*****************************************************
//Enable system clocks for input configuration
//*****************************************************
void Enable_Clocks()
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
}
//******************************************************
//******************************************************
//TIM2 interrupt
//******************************************************
void TIM2_IRQhandler()
{
static int CaptureNumber = 0;
static int IC3ReadValue1; // Retained
int IC3ReadValue2; // Transient
if (CaptureCount++ & 1) // Toggle PB11
GPIO_SetBits(GPIOB, GPIO_Pin_11);
else
GPIO_ResetBits(GPIOB, GPIO_Pin_11);
if (TIM2->SR & TIM_IT_CC3)
{
TIM2->SR = ~TIM_FLAG_CC3;
if(CaptureNumber == 0)
{
/* Get the Input Capture value */
IC3ReadValue1 = TIM2->CCR3;
CaptureNumber = 1;
}
else if(CaptureNumber == 1)
{
/* Get the Input Capture value */
IC3ReadValue2 = TIM2->CCR3;
/* Capture computation */
Capture = (IC3ReadValue2 - IC3ReadValue1) & 0xFFFF; // 16-bit masking
IC3ReadValue1 = IC3ReadValue2;
}
}
}
//******************************************************
//******************************************************
//Enable APB pin 10 for timer interrupt input
//******************************************************
void Enable_APB()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_TIM2); // PB10 TIM2_CH3
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB, GPIO_Pin_11);
}
//******************************************************
//******************************************************
//Enable TIM2 timer
//******************************************************
void Enable_Timer()
{
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_InitStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
// Configure NVIC first
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_InitStructure.TIM_Period = 0xFFFF; // Maximal
TIM_InitStructure.TIM_Prescaler = 32 - 1; // 1 MHz from 32 MHz
TIM_InitStructure.TIM_ClockDivision = 0;
TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_InitStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; // From the Pin
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; // Measuring period on fall edges
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
TIM_ITConfig(TIM2, TIM_IT_CC3, ENABLE);
TIM_ClearITPendingBit(TIM2, TIM_IT_CC3);
TIM_Cmd(TIM2, ENABLE);
}
//******************************************************
//******************************************************
//Main function calls all other functions when needed
//******************************************************
int main(void)
{
Enable_Clocks();
Enable_APB();
Enable_Timer();
/* Infinite loop */
while(1)
{
}
}
//******************************************************
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2013-09-11 10:31 PM
Thanks, you're the best.
I couldn't find any information regards to PB10 channel in reference manual. Where did you find it?
