2018-04-11 02:16 AM
Good day Sirs, I have the following issue:
MCU: STM32L152ZE
Software library: Standart Peripherial Library (supporting old project)I have need to count external pulses on PB3 input using TIM2 CH2.
Pulse train makes another timer using PWM, PB3 and PWM GPIO connected together, output signal checked with logic analyser - works. According to ' RM0038 Reference manual' the right way is to use timer in ' External clock source mode 1'.Following instruction on page 397 - the upcounter have to count in response to a rising edge on the TI2
input:1. Configure channel 2 to detect rising edges on the TI2 input by writing CC2S= ‘01 in the
TIMx_CCMR1 register. 2. Configure the input filter duration by writing the IC2F[3:0] bits in the TIMx_CCMR1 register (if no filter is needed, keep IC2F=0000). Note: The capture prescaler is not used for triggering, so there’s no need to configure it. 3. Select rising edge polarity by writing CC2P=0 and CC2NP=0 in the TIMx_CCER register. 4. Configure the timer in external clock mode 1 by writing SMS=111 in the TIMx_SMCR register. 5. Select TI2 as the input source by writing TS=110 in the TIMx_SMCR register. 6. Enable the counter by writing CEN=1 in the TIMx_CR1 register. When a rising edge occurs on TI2, the counter counts once and the TIF flag is set. The delay between the rising edge on TI2 and the actual clock of the counter is due to the resynchronization circuit on TI2 input.Clear.
GPIO_InitTypeDef GPIO_InitStruct;
// [0] enable port clock
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
// [1] config pin
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_PinAFConfig( GPIOB, GPIO_PinSource3, GPIO_AF_TIM2 ); // routing signal from pin to tim2
// [2] enable tim2 clock
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// [3] stop timer clock in debug (case of breakpoint)
DBGMCU_APB1PeriphConfig(DBGMCU_TIM2_STOP, ENABLE);
// [4] init a timer following instruction from reference manual:
uint16_t CCMR1 = 0;
uint16_t CCER = 0;
uint16_t SMCR = 0;
uint16_t CR1 = 0;
// CCMR1 Configure channel 2 to detect rising edges on the TI2 CC2S=01
CCMR1 |= TIM_CCMR1_CC2S_0;
// set input filter to IC2F=0x0F
//CCMR1 |= TIM_CCMR1_IC2F_0 | TIM_CCMR1_IC2F_1 | TIM_CCMR1_IC2F_2 | TIM_CCMR1_IC2F_3;
// set input filter to IC2F=0x00 nothing to do with IC2F
TIM2->CCMR1 = CCMR1;
// TIM_CCER_CC2P=0 and TIM_CCER_CC2NP = 0 so nothing to do
TIM2->CCER = CCER;
// Configure the timer in external clock mode 1 SMS=111
SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_1 |TIM_SMCR_SMS_2;
// Select TI2 as the input source TS=110
SMCR |= TIM_SMCR_TS_2 | TIM_SMCR_TS_1;
TIM2->SMCR = SMCR;
// set CNT=0 and ARR to MAX.
TIM2->CNT = 0;
TIM2->ARR = 0xFFFF;
// start timer
TIM2->CR1 = TIM_CR1_CEN;�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
if I make stop in the breakpoint after pulse train TIM2->CNT still 0;
The values of tim registers the same as set values.
Whatdid I wrong with tim configuration? Looking forward for any help. #pulse-counter #external-clock-source #spl #tim #stm32l152 #timer2018-04-11 04:22 AM
Looks OK at the first sight.
Post the read out values of both relevant GPIO registers and the timer register.
JW
2018-04-11 07:52 AM
Thanks for attention,waclawek.jan!
Here the read values of TIM2 and GPIOB registers from debugger.
TIM2 DMAR register value is a surprise. DMA not used in this project, blank project - only timer init.TIM2 registers:
CR1= 0x00000001 CEN=1
CR2 = 0x00000000
SMCR = 0x00000067 TS=110 SMS=111
DIER -
SR = 0x00000001
EGR= 0x00000000
CCMR1= 0x00000100 CC2S=01
CCMR2= 0x00000000
CCER= 0x00000000
CNT= 0x00000000
PSC= 0x00000000
ARR= 0x0000FFFF
CCR1= 0x00000000
CCR2= 0x00000000
CCR3= 0x00000000
CCR4= 0x00000000
DCR= 0x00000000
DMAR= 0x00000001 ??? unpredictable
GPIOB registers value:
MODER3 = 0x01005290MODER3= 10
OTYPER = 0x00000000
OSPEEDER= 0x0100f210OSPEEDER3 = 00
PUPDR= 0xAA000320PUPDR3 = 00
IDR= 0x00003377IDR3= 00
ODR= 0x00001044ODR3= 00
BSRR= -
LCKR= 0x00000000
AFRL= 0x00001000AFRL2= 0001
AFRH= 0x00001000�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
2018-04-11 11:02 AM
This all looks good.
If you change the pin's level externally, can you see the respective bit in GPIO_IDR to change? (this question is aimed at bad solder joints at the pin)
JW
2018-04-11 12:02 PM
I see that you have other pins configured, so this is probably part of some larger project. Can't the TIM2_CH2 be inadvertently configured on some other pin too?
I suggest you to start an absolute minimal project just to check this one particular issue.
JW
PS. Ah the TIM_DMAR - don't bother about it. It's not a register - it's a 'window' into other registers, useful only when the DMA-to-timers-registers feature is used.
2018-04-11 12:03 PM
Using external wire jumper and voltmeter found:
PB3 connected to VDD(3.3V) IDR3=1
PB3 connected to GND IDR3=0.
I think no bad solder.Still no idea,
Daniil Kupchyk2018-04-12 01:56 AM
Dear
JW
,following your recomendation I have created minimal project and it works, timer conts external pulses... but counts with pulses loss at start.
EXTERNAL PULSES ON PIN: 6 11 16 21 26 251
TIMER COUNTED PULSES : 9 14 19 24 29 254�?�?�?�?
In all cases difference between generated pulses and counted is 3. Input filter doesn't used.
Should I do a correction in CNT register before timer start?
For example:
TIM2->CNT = 3;
TIM2->CR1 |= TIM_CR _CEN;�?�?
The right solution is near,
Daniil Kupchyk.2018-04-12 02:21 PM
It appears that the number in TIM_CNT is already 3 higher, so adding 3 more the difference will be 6...?
But it's always better to remove the cause than to make cosmetic changes. Can't the problem be in sequencing of the actions - do you enable the timer as the last thing, after all GPIO and TIM settings have been already done? Is the input pulse 'sharp' enough, or does it have a significant up or down slope?
JW