Page 1 of 1
TIM2 TIM5 Gated mode
Posted: Tue Jan 13, 2015 9:02 am
by klik
Hi everyone,
first of all I have to say I like the pyboard. It is tiny and you can develop software really fast for it. But at the moment I'm stuck. I try to get the TIM2 and TIM5 (32 bit) working in the gated mode.
I want to start counting as long as a pin is high (or low).
TIM2 CH2 Pin.X2
I found the Timer Control Register 1 etc.
http://wiki.micropython.org/platforms/b ... -const-tim
Enabling a counter is not the deal. But it does not work in the gated mode.
I hope someone here can help me.
Big thx
Re: TIM2 TIM5 Gated mode
Posted: Wed Jan 14, 2015 8:01 am
by dhylands
The timers (in micropython) don't directly support the gated mode, but input capture mode gets us most of the way there.
So I put together an example which i put in my github repository:
https://github.com/dhylands/upy-example ... r/gated.py
Code: Select all
import pyb
import stm
# For this example, we assume that there is a wire connected from X1 to Y1
#
# Y1 corresponds to Timer 8 channel 1, which we'll use as output
# X1 corresponds to Timer 2 channel 1, which we'll use an the input gate
#
# We'll confgure Y1 as a GPIO and initially drive it high (which corresponds
# to not counting). Then we'll toggle that pin when the user presses a key.
y1 = pyb.Pin('Y1', pyb.Pin.OUT_PP)
y1.high()
# tim2's source_freq is 84 MHz, so we'll set the prescalar to divide by
# 8399, which will drop the counter freq to 10 kHz, and we'll set the
# period to be 50,000 clock ticks, so that it rolls over once every 5 seconds
#
# Note that the prescalar for tim2 is 16-bit but the period is 32-bit.
tim2 = pyb.Timer(2, prescaler=8399, period=49999)
# We're following the example on page 603 of the RM0090 document (STM32F405
# datasheet) (I copied the pertinent section below for reference):
#
# Slave mode: Gated mode
#
# The counter can be enabled depending on the level of a selected input.
# In the following example, the upcounter counts only when TI1 input is low:
#
# - Configure the channel 1 to detect low levels on TI1. Configure the
# input filter duration (in this example, we don't need any filter, so
# we keep IC1F=0000). The capture prescaler is not used for triggering,
# so you don't need to configure it. The CC1S bits select the input
# capture source only, CC1S=01 in TIMx_CCMR1 register. Write CC1P=1
# and CC1NP=0 in TIMx_CCER register to validate the polarity (and
# detect low level only).
#
# - Configure the timer in gated mode by writing SMS=101 in TIMx_SMCR
# register. Select TI1 as the input source by writing TS=101 in
# TIMx_SMCR register.
#
# - Enable the counter by writing CEN=1 in the TIMx_CR1 register (in
# gated mode, the counter doesn't start if CEN=0, whatever is the
# trigger input level).
#
# The counter starts counting on the internal clock as long as TI1 is low
# and stops as soon as TI1 becomes high. The TIF flag in the TIMx_SR register
# is set both when the counter starts or stops.
#
# If we set the channel up for input capture, then it will set CC1S to 01
# Setting the polarity to FALLING will set CC1P=1 and CC1NP=0
ch1 = tim2.channel(1, pyb.Timer.IC, pin=pyb.Pin.board.X1, polarity=pyb.Timer.FALLING)
# We'll need to set the SMS=101 and TS=101 in the SMCR register ourselves,
# since none of the exposed APIs manipulate that register.
#
# SMS is bits 2:0 and TS is bits 6:4
smcr = stm.mem16[stm.TIM2 + stm.TIM_SMCR]
smcr &= 0b1111111110001000
smcr |= 0b0000000001010101
stm.mem16[stm.TIM2 + stm.TIM_SMCR] = smcr
usb_vcp = pyb.USB_VCP()
while True:
if usb_vcp.any():
ch = usb_vcp.read()
if y1.value():
print("Counter enabled")
y1.low()
else:
y1.high()
print("Counter disabled")
pyb.delay(100)
cnt = tim2.counter()
print('cnt = %d' % cnt)
This example requires a jumper wire from X1 to Y1. Some sample output looks like this:
Code: Select all
>>> import gated
cnt = 0
cnt = 0
Counter enabled
cnt = 997
cnt = 1997
cnt = 2997
cnt = 3997
cnt = 4997
cnt = 5997
cnt = 6997
cnt = 7997
cnt = 8997
cnt = 9997
cnt = 10997
cnt = 11997
cnt = 12997
cnt = 13997
Counter disabled
cnt = 13999
cnt = 13999
...
cnt = 13999
cnt = 13999
Counter enabled
cnt = 14997
cnt = 15997
cnt = 16997
cnt = 17997
cnt = 18997
cnt = 19997
cnt = 20997
cnt = 21997
cnt = 22997
cnt = 23997
cnt = 24997
cnt = 25997
cnt = 26997
cnt = 27997
cnt = 28997
cnt = 29997
cnt = 30997
cnt = 31997
cnt = 32997
cnt = 33997
Counter disabled
cnt = 33999
cnt = 33999
...
\cnt = 33999
cnt = 33999
Counter enabled
cnt = 34996
cnt = 35996
cnt = 36996
cnt = 37996
cnt = 38996
cnt = 39996
cnt = 40996
cnt = 41996
cnt = 42996
cnt = 43996
cnt = 44996
cnt = 45996
cnt = 46996
cnt = 47996
cnt = 48996
cnt = 49996
cnt = 996
cnt = 1996
cnt = 2996
Counter disabled
cnt = 2999
cnt = 2999
...
cnt = 2999
cnt = 2999
Counter enabled
cnt = 3996
cnt = 4996
cnt = 5996
cnt = 6996
cnt = 7996
cnt = 8996
cnt = 9996
cnt = 10996
cnt = 11996
cnt = 12996
cnt = 13996
cnt = 14996
cnt = 15996
Counter disabled
cnt = 15999
cnt = 15999
cnt = 15999
Re: TIM2 TIM5 Gated mode
Posted: Wed Jan 14, 2015 10:12 pm
by Damien
Nice work @dhylands! Do you think it's worth adding a proper gated mode to the timers to make this easier to do?
Re: TIM2 TIM5 Gated mode
Posted: Thu Jan 15, 2015 7:26 am
by dhylands
Damien wrote:Nice work @dhylands! Do you think it's worth adding a proper gated mode to the timers to make this easier to do?
Probably. I dug through the hal, and it looks like ther is support for slave mode configuration via HAL_TIM_SlaveConfigSynchronization
Right now my thinking is that this would be easiest to add as an extra mode (like IC, PWM) probably called SLAVE.
Re: TIM2 TIM5 Gated mode
Posted: Fri Jan 16, 2015 4:48 pm
by klik
So finally I have found some time to get a closer look at the code and the STM32F4 datasheet.
@dhylands
thank you for your help. But it seems to be merely a polling solution. The while: looks at the Port until it is set. I guess it would work. But not exactly what I was looking for.
But i think, I finally found a solution.
Code: Select all
import pyb
import stm
def initTIM2Gated():
stm.mem32[stm.TIM2 + stm.TIM_SMCR] = 0x0000
stm.mem32[stm.TIM2 + stm.TIM_SMCR] = 0x0070
stm.mem32[stm.TIM2 + stm.TIM_SMCR] = 0x0075
def initTIM5Gated():
stm.mem32[stm.TIM5 + stm.TIM_SMCR] = 0x0000
stm.mem32[stm.TIM5 + stm.TIM_SMCR] |= 0x0055
initTIM2Gated()
initTIM5Gated()
timer2 = pyb.Timer(2, prescaler=0, period=0x3FFFFFFF)
pin1 = pyb.Pin(pyb.Pin.board.X6, mode=pyb.Pin.AF_PP, af=pyb.Pin.AF1_TIM2)
timer2.counter(0)
timer5 = pyb.Timer(5, prescaler=0, period=0x3FFFFFFF)
pin5 = pyb.Pin(pyb.Pin.board.X1, mode=pyb.Pin.AF_PP, af=pyb.Pin.AF2_TIM5)
timer5.counter(0)
def c():
global timer2, timer5
timer2.counter(0)
timer5.counter(0)
def r():
while(1):
pyb.delay(50)
print("TIM2")
print(timer2.counter())
print(pin1.value())
print("TIM5")
print(timer5.counter())
print(pin5.value())
print("\n")
c()
r()
The code does the job. Hope I didn't set the self destruction register somewhere. Hope it will be available in a further release like PWM, GATED, ...
Re: TIM2 TIM5 Gated mode
Posted: Fri Jan 16, 2015 5:51 pm
by dhylands
klik wrote:So finally I have found some time to get a closer look at the code and the STM32F4 datasheet.
@dhylands
thank you for your help. But it seems to be merely a polling solution. The while: looks at the Port until it is set. I guess it would work. But not exactly what I was looking for.
The while loop was just for controlling the "gate". I'm assuming that you've got other HW for doing that.
klik wrote:But i think, I finally found a solution.
Code: Select all
import pyb
import stm
def initTIM2Gated():
stm.mem32[stm.TIM2 + stm.TIM_SMCR] = 0x0000
stm.mem32[stm.TIM2 + stm.TIM_SMCR] = 0x0070
stm.mem32[stm.TIM2 + stm.TIM_SMCR] = 0x0075
def initTIM5Gated():
stm.mem32[stm.TIM5 + stm.TIM_SMCR] = 0x0000
stm.mem32[stm.TIM5 + stm.TIM_SMCR] |= 0x0055
initTIM2Gated()
initTIM5Gated()
timer2 = pyb.Timer(2, prescaler=0, period=0x3FFFFFFF)
pin1 = pyb.Pin(pyb.Pin.board.X6, mode=pyb.Pin.AF_PP, af=pyb.Pin.AF1_TIM2)
timer2.counter(0)
timer5 = pyb.Timer(5, prescaler=0, period=0x3FFFFFFF)
pin5 = pyb.Pin(pyb.Pin.board.X1, mode=pyb.Pin.AF_PP, af=pyb.Pin.AF2_TIM5)
timer5.counter(0)
def c():
global timer2, timer5
timer2.counter(0)
timer5.counter(0)
def r():
while(1):
pyb.delay(50)
print("TIM2")
print(timer2.counter())
print(pin1.value())
print("TIM5")
print(timer5.counter())
print(pin5.value())
print("\n")
c()
r()
The code does the job. Hope I didn't set the self destruction register somewhere. Hope it will be available in a further release like PWM, GATED, ...
Just be careful. When you do stuff like: stm.mem32[stm.TIM2 + stm.TIM_SMCR] = 0x0000 you're zeroing ALL of the fields in the register.
Maybe I misunderstood what you were trying to do. It looks like you're trying to use one timer to gate another? If so, then I missed that detail.