cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103 Timer input capture disables USART - problem

robertnoble9
Associate III
Posted on March 08, 2016 at 08:19

Hi all,

I am new this forum so bear with me. I am working on a project using an STM32F103RBT6 that incorporates a timer in input capture mode (TIM2) and a USART (USART3). I can successfully enable the USART and transmit data over a USB to TTLcable to a laptop. The problem is when I try to set up the timer. As soon a I include the timer initialisation code using TIM_ICInit, the USART stops working and nothing comes through to the computer. I'm hoping someone here could shed some light on it. I'm assuming I have made some school boy error and not realised. I have included some of my code below. Thanks in advance Look forward to hearing from you all. Rob USART set up:

USART_InitTypeDef USART_InitStructure; 
/* set up with baud rate at 115200, Tx and Rx mode */
USART_InitStructure.USART_BaudRate = 115200; 
USART_InitStructure.USART_WordLength = USART_WordLength_8b; 
USART_InitStructure.USART_StopBits = USART_StopBits_1; 
USART_InitStructure.USART_Parity = USART_Parity_No ; 
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; 
USART_Init(USART3, &USART_InitStructure); 
USART_Cmd(USART3,ENABLE);

Timer set up:

TIM_ICInitTypeDef TIM_ICInitStructure; 
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_BothEdge; 
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; 
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; 
TIM_ICInitStructure.TIM_ICFilter = 0x0; 
// initialise channel 1 
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; 
TIM_ICInit(TIM2, &TIM_ICInitStructure); 
/* TIM enable counter */
TIM_Cmd(TIM2, ENABLE);

16 REPLIES 16
Walid FTITI_O
Senior II
Posted on March 08, 2016 at 11:54

Hi minthemerciless, 

Can you provide more details about the GPIOs configuration and the funtions calling sequence in the main (including the clock enabling ones).

-Hannibal-

robertnoble9
Associate III
Posted on March 08, 2016 at 12:48

Hi Hannibal,

In total therewill beTIM2 in input capture mode, TIM3 in input capture mode and TIM4 in PWM output mode. At the moment I only have the PWM out enabled, with no USART problems. Issues occur when either TIM2 or TIM3 are configured and enable din input capture mode. Hopefully the code below helps. Thanks for the help

int
main(
void
) 
{ 
/* Configure SysTick to count at 1ms */
SysTick_Config(SystemCoreClock / 1000); 
/* Set usTicks */
cycleCounterInit(); 
/* System Clocks Configuration */
RCC_Configuration(); 
/* Configure the GPIO ports */
GPIO_Configuration(); 
/* NVIC configuration */
NVIC_Configuration(); 
/* USART configuration */
USART_Configuration(); 
/* TIMER Configuration */
TIM_Configuration(); 
/* write some text */
writeStringUSART3(
''Initialisation complete.

''
); 
while
(1) 
{ 
} 
} 
void
RCC_Configuration(
void
) 
{ 
/* TIM2 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); 
/* TIM3 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); 
/* TIM4 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); 
/* GPIOA clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 
/* GPIOB clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); 
/* USART3 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); 
} 
void
GPIO_Configuration(
void
) 
{ 
GPIO_InitTypeDef GPIO_InitStructure; 
/* TIM2 channel 1, 2, 3, 4 pin configuration for inputs */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_Init(GPIOA, &GPIO_InitStructure); 
/* TIM3 */
/* channel 1, 2 pin configuration for inputs */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_Init(GPIOA, &GPIO_InitStructure); 
/* channel 3, 4 pin configuration for inputs */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_Init(GPIOB, &GPIO_InitStructure); 
/* TIM 4 */
/* channel 1, 2, 3, 4 pin configuration as outputs for PWM mode */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; 
GPIO_Init(GPIOB, &GPIO_InitStructure); 
/* USART3 */
/* PB.10 is Tx on USART3 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
GPIO_Init(GPIOB, &GPIO_InitStructure); 
/* PB.11 is Rx on USART3 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 
GPIO_Init(GPIOB, &GPIO_InitStructure); 
} 
void
NVIC_Configuration(
void
) 
{ 
NVIC_InitTypeDef NVIC_InitStructure; 
/* Enable the TIM2 global Interrupt 
used for command inputs */
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); 
/* Enable the TIM3 global Interrupt 
used for rpm inputs */
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; 
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
NVIC_Init(&NVIC_InitStructure); 
} 
void
USART_Configuration(
void
) 
{ 
USART_InitTypeDef USART_InitStructure; 
/* set up with baud rate at 115200, Tx and Rx mode */
USART_InitStructure.USART_BaudRate = 115200; 
USART_InitStructure.USART_WordLength = USART_WordLength_8b; 
USART_InitStructure.USART_StopBits = USART_StopBits_1; 
USART_InitStructure.USART_Parity = USART_Parity_No ; 
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; 
USART_Init(USART3, &USART_InitStructure); 
USART_Cmd(USART3,ENABLE); 
} 
void
TIM_Configuration(
void
) 
{ 
TIM_ICInitTypeDef TIM_ICInitStructure; 
/* TIM2 configuration ------------------------ 
The external signal is connected to TIM2 CH1-4 pin (PA.00-PA.03), 
Both rising and falling edges are used, 
------------------------------------------------------------ */
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_BothEdge; 
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; 
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; 
TIM_ICInitStructure.TIM_ICFilter = 0x0; 
// initialise channel 1 
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; 
TIM_ICInit(TIM2, &TIM_ICInitStructure); 
// initialise channel 2 
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; 
TIM_ICInit(TIM2, &TIM_ICInitStructure); 
// initialise channel 3 
TIM_ICInitStructure.TIM_Channel = TIM_Channel_3; 
TIM_ICInit(TIM2, &TIM_ICInitStructure); 
// initialise channel 4 
TIM_ICInitStructure.TIM_Channel = TIM_Channel_4; 
TIM_ICInit(TIM2, &TIM_ICInitStructure); 
/* TIM enable counter */
TIM_Cmd(TIM2, ENABLE); 
/* TIM4 configuration ------------------------ 
used for PWM outputs on GPIOB channels 1,2,3,4 */
TIM_OCInitTypeDef TIM_OCInitStructure; 
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 
uint32_t prescaleDivisor; 
float
initialDuty = 0.1; 
prescaleDivisor = outputTimerPeriod * outputFrequency; 
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Prescaler = ((SystemCoreClock / prescaleDivisor)) - 1; 
TIM_TimeBaseStructure.TIM_Period = outputTimerPeriod - 1; 
TIM_TimeBaseStructure.TIM_ClockDivision = 0; 
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); 
/* Enable Preload register on ARR */
TIM_ARRPreloadConfig(TIM4, ENABLE); 
/* TIM PWM1 Mode configuration */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; 
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable; 
TIM_OCInitStructure.TIM_Pulse = outputTimerPeriod * initialDuty; 
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; 
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; 
// channel 1 
TIM_OC1Init(TIM4, &TIM_OCInitStructure); 
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable); 
// channel 2 
TIM_OC2Init(TIM4, &TIM_OCInitStructure); 
TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Enable); 
// channel 3 
TIM_OC3Init(TIM4, &TIM_OCInitStructure); 
TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable); 
// channel 4 
TIM_OC4Init(TIM4, &TIM_OCInitStructure); 
TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable); 
/* TIM enable counter */
TIM_Cmd(TIM4, ENABLE); 
}

Posted on March 08, 2016 at 15:05

Code still looks incomplete. Post a complete/concise example that demonstrates the failure.

Using C++ or .cpp? Watch for name mangling of the IRQHandler names.

I'd initialize the time base before the channels. Make sure the structures are completely initialized.

Is the software locking up somewhere, or faulting? Review with a debugger.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
robertnoble9
Associate III
Posted on March 09, 2016 at 13:06

I don't currently have a debugger.  I have one on order, hoping to get it later this week.  It seems it is faulting during the call to TIM_ICInit and causing what looks like a reset and thus getting stuck in a loop.  I have not yet found what is causing the fault yet.

AvaTar
Lead
Posted on March 09, 2016 at 13:37

> I don't currently have a debugger.

 

''Debugger'' is a somehow generically used term in this context.

Here, it means the combination of a JTAG or SWD adapter and a software, usually included in your toolchain/IDE.

If you use a Discovery or Nucleo board and one of the common toolchains that support the ST-Link, you already have a ''debugger''. And, you can modify Discovery/Nucleo boards to use the onboard - debug adapter to debug other boards.

robertnoble9
Associate III
Posted on March 09, 2016 at 15:48

I shall rephrase.  I have an ST LINK on order.  I am currently working with a Leaflabs Maple board which doesn't have an on-board debug adapter.

AvaTar
Lead
Posted on March 09, 2016 at 15:56

> I shall rephrase.  I have an ST LINK on order.  I am currently working with a Leaflabs Maple board which doesn't have an on-board debug adapter.

 

In that case, I would have ordered a different debug adapter (like the J-Link), with support for other vendors, and broader toolchain support.

Just my personal opinion.

robertnoble9
Associate III
Posted on March 09, 2016 at 16:15

I am quite new to the world of microcontrollers, so an ST LINK felt like a safe  (and cheap) option.  Searching for J LINK adaptors, the cost s seems to range wildly, which doesn't fill with confidence in terms of selecting the correct item.  If you have any insight or recommendations, that would be very helpful.

Back on topic,  Am I correct to think that a fault somewhere is causing the resetting on the board and making it loop back to the start each time?

AvaTar
Lead
Posted on March 09, 2016 at 16:58

As always, this depends on your requirements.

A J-Link is often sold quite cheaply together with some (equally cheap) evaluation boards (like FM3/FM4 eval board from Cypress). A CMSIS-DAP adapter would be an alternative - supported by many toolchains, and often used as onboard adapter (like ST's onboard ST-Link).

However, I have successfully used a ST-Link (a full one like you ordered) to flash and debug NXP controllers - albeit two years ago.

My only recommendation would be to think twice before spending big money on a debug pod 'bound' to one company/toolchain, like I-Jet (IAR), CrossConnect (Rowley/Crossworks), or ICDI (TI).

> Back on topic,  Am I correct to think that a fault somewhere is causing the resetting on the board and making it loop back to the start each time?

 

Normally not. The default implementation of the hardfault handler (and other fault handlers) is the endless loop. The idea is, when such an unexpected error happens be it hardware or software related, better do nothing than do any harm. MCU's are often used in unaccessible places, without a reset button or a keyboard for a Ctrl-Alt-Del.

You can add any code to the hardfault handler you wish to output diagnostics - but expect a compromised environment, like a corrupted stack. AFAIK, a hardfault in the hardfault-handler means a lock-up, only to exit via reset.

BTW, such core-related behavior is well documented at

http://infocenter.arm.com

, a suggested source for information that are missing in the ST documents.