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
TIM2 TIM5 Gated mode
Re: TIM2 TIM5 Gated mode
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
This example requires a jumper wire from X1 to Y1. Some sample output looks like this:
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)
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
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
Probably. I dug through the hal, and it looks like ther is support for slave mode configuration via HAL_TIM_SlaveConfigSynchronizationDamien wrote:Nice work @dhylands! Do you think it's worth adding a proper gated mode to the timers to make this easier to do?
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
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.
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, ...
@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()
Re: TIM2 TIM5 Gated mode
The while loop was just for controlling the "gate". I'm assuming that you've got other HW for doing that.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.
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.klik wrote:But i think, I finally found a solution.
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, ...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()
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.