Skip to content

Instantly share code, notes, and snippets.

@nmz787
Last active December 14, 2019 19:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nmz787/edd964e9f06ade61de75fbc38bee9b8e to your computer and use it in GitHub Desktop.
Save nmz787/edd964e9f06ade61de75fbc38bee9b8e to your computer and use it in GitHub Desktop.
ok, seems I have 2 glitch-free PWM channels which are 180 degrees out-of-phase... controllable for pulse width and period at the top with two variables. TIM1 starts TIM2 and TIM5... then after a number of interrupts on TIM2, it shuts itself down and attaches a shutdown-timer to TIM3
import pyb
from pyb import Timer
import micropython
import stm
#john's sript actual pulse width 181 us, 448 us period (pulse to pulse)
# Use with pyb.freq(96000000) and prescaler=11 for .25 usec timer ticks.
xfmr_pulse_period = 1570 # (= usec * 4) Same as toggle_half_cycle duration.
xfmr_pulse_w = 332 # (= usec * 4)
max_push_pulls = 8
def force_inactive1():
# Put (t2ch2/t2ch1) mode to FORCED_INACTIVE to start...
# TODO which isn it, ch1 or ch2?
# TODO link to PDF and page number for register field description
ccmr1 = stm.mem16[stm.TIM2 + stm.TIM_CCMR1]
ccmr1 &= 0b1111111110001111 # OC2M "100"....OC1M "100"
ccmr1 |= 0b0000000001000000
stm.mem16[stm.TIM2 + stm.TIM_CCMR1] = ccmr1
def force_inactive2():
# Put (t2ch2/t2ch1) mode to FORCED_INACTIVE to start...
# TODO which isn it, ch1 or ch2?
# TODO link to PDF and page number for register field description
ccmr1 = stm.mem16[stm.TIM2 + stm.TIM_CCMR1]
ccmr1 &= 0b1000111111111111 # OC2M "100"....OC1M "100"
ccmr1 |= 0b0100000000000000
stm.mem16[stm.TIM2 + stm.TIM_CCMR1] = ccmr1
def force_inactive5():
# Put (t2ch2/t2ch1) mode to FORCED_INACTIVE to start...
# TODO which isn it, ch1 or ch2?
# TODO link to PDF and page number for register field description
ccmr1 = stm.mem16[stm.TIM5 + stm.TIM_CCMR1]
ccmr1 &= 0b1000111110001111 # OC2M "100"....OC1M "100"
ccmr1 |= 0b0100000001000000
stm.mem16[stm.TIM5 + stm.TIM_CCMR1] = ccmr1
def force_inactive():
# Put t2ch2 t2ch1 mode to FORCED_INACTIVE to start...
ccmr1 = stm.mem16[stm.TIM2 + stm.TIM_CCMR1]
ccmr1 &= 0b1000111110001111 # OC2M "100"....OC1M "100"
ccmr1 |= 0b0100000001000000
stm.mem16[stm.TIM2 + stm.TIM_CCMR1] = ccmr1
def ccer_set(enable=True):
# Put t2ch2 t2ch1 mode to FORCED_INACTIVE to start...
#ccmr1 = stm.mem16[stm.TIM2 + stm.TIM_CCMR1]
val = stm.mem16[stm.TIM2 + stm.TIM_CCER]
# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# Reserved CC4P CC4E CC3NP CC3NE CC3P CC3E CC2NP CC2NE CC2P CC2E CC1NP CC1NE CC1P CC1E
val &= 0b1111111111101110 # TIM_CC2E TIM_CC1E
if enable:
val |= 0b0000000000010001
#else:
# val |= 0b0000000000000000
stm.mem16[stm.TIM2 + stm.TIM_CCER] = val
def ccer_set5(enable=True):
# Put t2ch2 t2ch1 mode to FORCED_INACTIVE to start...
#ccmr1 = stm.mem16[stm.TIM2 + stm.TIM_CCMR1]
val = stm.mem16[stm.TIM5 + stm.TIM_CCER]
# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# Reserved CC4P CC4E CC3NP CC3NE CC3P CC3E CC2NP CC2NE CC2P CC2E CC1NP CC1NE CC1P CC1E
val &= 0b1111111111101110 # TIM_CC2E TIM_CC1E
if enable:
val |= 0b0000000000010001
# else:
# val |= 0b0000000000000000
stm.mem16[stm.TIM5 + stm.TIM_CCER] = val
def tim1_cr1_set(enable=True):
val = stm.mem16[stm.TIM1 + stm.TIM_CR1]
# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# Reserved CKD[1:0] ARPE CMS DIR OPM URS UDIS CEN
val &= 0b1111111111111110 # CEN off
if enable:
val |= 0b0000000000000001 # CEN on
stm.mem16[stm.TIM1 + stm.TIM_CR1] = val
def tim2_cr1_set(enable=True):
# Put t2ch2 t2ch1 mode to FORCED_INACTIVE to start...
#ccmr1 = stm.mem16[stm.TIM2 + stm.TIM_CCMR1]
val = stm.mem16[stm.TIM2 + stm.TIM_CR1]
# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# Reserved CKD[1:0] ARPE CMS DIR OPM URS UDIS CEN
val &= 0b1111111111111110 # CEN off
if enable:
val |= 0b0000000000000001 # CEN on
stm.mem16[stm.TIM2 + stm.TIM_CR1] = val
@micropython.native
def tim2_cr1_disable_clock():
# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# Reserved CKD[1:0] ARPE CMS DIR OPM URS UDIS CEN
stm.mem16[stm.TIM2] &= 0b1111111111111110 # CEN off
#stm.mem16[stm.TIM2]&=((~1) & 0xffffffff)
@micropython.native
def tim5_cr1_disable_clock():
# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# Reserved CKD[1:0] ARPE CMS DIR OPM URS UDIS CEN
stm.mem16[stm.TIM5] &= 0b1111111111111110 # CEN off
#stm.mem16[stm.TIM5]&=((~1) & 0xffffffff)
@micropython.native
def tim3_cr1_disable_clock():
# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# Reserved CKD[1:0] ARPE CMS DIR OPM URS UDIS CEN
stm.mem16[stm.TIM3] &= 0b1111111111111110 # CEN off
def tim5_cr1_set(enable=True):
# Put t2ch2 t2ch1 mode to FORCED_INACTIVE to start...
#ccmr1 = stm.mem16[stm.TIM2 + stm.TIM_CCMR1]
val = stm.mem16[stm.TIM5 + stm.TIM_CR1]
# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# Reserved CKD[1:0] ARPE CMS DIR OPM URS UDIS CEN
val &= 0b1111111111111110 # CEN off
if enable:
val |= 0b0000000000000001 # CEN on
stm.mem16[stm.TIM5 + stm.TIM_CR1] = val
def tim1_cr2_set(enable=True):
# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# Reserved TI1S MMS[2:0] CCDS Reserved
val = stm.mem16[stm.TIM1 + stm.TIM_CR2]
val &= 0b1111111110001111
val |= 0b0000000000100000
stm.mem16[stm.TIM1 + stm.TIM_CR2] = val
def tim2_cr2_set(enable=True):
# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# Reserved TI1S MMS[2:0] CCDS Reserved
val = stm.mem16[stm.TIM2 + stm.TIM_CR2]
val &= 0b1111111110001111
val |= 0b0000000000000000
stm.mem16[stm.TIM2 + stm.TIM_CR2] = val
def tim5_cr2_set(enable=True):
# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# Reserved TI1S MMS[2:0] CCDS Reserved
pass
def tim2_smcr_():
# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# ETP ECE ETPS[1:0] ETF[3:0] MSM TS[2:0] Res. SMS[2:0]
val = stm.mem16[stm.TIM2 + stm.TIM_SMCR]
val &= 0b1111111110001000
val |= 0b0000000000000110
stm.mem16[stm.TIM2 + stm.TIM_SMCR] = val
def tim3_smcr_():
# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# ETP ECE ETPS[1:0] ETF[3:0] MSM TS[2:0] Res. SMS[2:0]
val = stm.mem16[stm.TIM3 + stm.TIM_SMCR]
val &= 0b1111111110001000
val |= 0b0000000000000110
stm.mem16[stm.TIM3 + stm.TIM_SMCR] = val
def tim5_smcr_():
# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# ETP ECE ETPS[1:0] ETF[3:0] MSM TS[2:0] Res. SMS[2:0]
val = stm.mem16[stm.TIM5 + stm.TIM_SMCR]
val &= 0b1111111110001000
val |= 0b0000000000000110
stm.mem16[stm.TIM5 + stm.TIM_SMCR] = val
def preload_enable():
# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# OC2CE OC2M[2:0] OC2PE OC2FE CC2S[1:0] OC1CE OC1M[2:0] OC1PE OC1FE CC1S[1:0]
ccmr1 = stm.mem16[stm.TIM2 + stm.TIM_CCMR1]
#ccmr1 &= 0b1111111111111111 # OC2M "100"....OC1M "100"
ccmr1 |= 0b0000100000001000
stm.mem16[stm.TIM2 + stm.TIM_CCMR1] = ccmr1
def preload_enable5():
# 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
# OC2CE OC2M[2:0] OC2PE OC2FE CC2S[1:0] OC1CE OC1M[2:0] OC1PE OC1FE CC1S[1:0]
ccmr1 = stm.mem16[stm.TIM5 + stm.TIM_CCMR1]
#ccmr1 &= 0b1111111111111111 # OC2M "100"....OC1M "100"
ccmr1 |= 0b0000100000001000
stm.mem16[stm.TIM5 + stm.TIM_CCMR1] = ccmr1
micropython.alloc_emergency_exception_buf(100)
print('\nStarting now\n')
lower_events = 0
events = 0
events_max_push_pulls = max_push_pulls
half_pulse= xfmr_pulse_w//2
adc = pyb.ADC(pyb.Pin.board.JP29)
#preload_enable()
t1 = pyb.Timer(1, prescaler=1, period=0x0FFFFFFF)
tim1_cr1_set(False)
# Timer 2 to give .125 usec timer ticks counting up:
t2 = pyb.Timer(2, prescaler=11, period=xfmr_pulse_period, mode=Timer.CENTER)
tim2_cr1_disable_clock()
# 26 is delay for start-up time for attaching callback in the disable-code
t3 = pyb.Timer(3, prescaler=11, period=xfmr_pulse_period+26, mode=Timer.CENTER)
tim3_cr1_disable_clock()
t3.counter(0)
t5 = pyb.Timer(5, prescaler=11, period=xfmr_pulse_period, mode=Timer.CENTER)
tim5_cr1_disable_clock()
#force_inactive5()
#preload_enable()
#preload_enable5()
#force_inactive()
#ccer_set(False)
force_inactive5()
force_inactive()
t2.counter(0)
t5.counter(0)
tim5_cr1_disable_clock()
tim1_cr2_set()
tim2_smcr_()
tim3_smcr_()
tim5_smcr_()
# upper trace, PA0
upper = t5.channel(1, pyb.Timer.PWM, pulse_width=xfmr_pulse_w,
polarity=pyb.Timer.HIGH, pin=pyb.Pin.board.JP25)
tim5_cr1_disable_clock()
ccer_set5(False)
#tim5_cr1_set(False)
#tim5_cr1_disable_clock()
# bottom trace, PA1
lower = t2.channel(2, pyb.Timer.PWM, pulse_width=xfmr_pulse_w,
polarity=pyb.Timer.HIGH, pin=pyb.Pin.board.JP26)
#tim2_cr1_set(False)
#tim2_cr1_set_alternate(False)
tim2_cr1_disable_clock()
#ic = t1.channel(4, Timer.IC, pin=pyb.Pin.board.JP26, polarity=pyb.Timer.BOTH)
# adc_timer = t1.channel(4, pyb.Timer.OC_TIMING)
# def adc_cb(the_active_timer):
# print(adc.read())
# adc_timer.callback(adc_cb)
#@micropython.native
def disable_upper(the_active_timer):
global events
#print('upper')
events += 1
if events==events_max_push_pulls:
#t2.deinit()
#ccer_set5(False)
while pyb.Pin.board.JP25.value():
print('upper')
print(adc.read())
#ccer_set5(False)
#stm.mem16[stm.TIM2 + stm.TIM_CR1] = 0
#tim5_cr1_set(False)
#t2.deinit()
#the_active_timer.deinit()
force_inactive5()
force_inactive()
def shutdown_timer(the_active_timer):
force_inactive5()
#@micropython.native
def disable_lower(the_active_timer):
global lower_events
#print('lower')
lower_events+=1
if lower_events==events_max_push_pulls:
#the_active_timer.period(half_pulse)
#lower.pulse_width(0)
while pyb.Pin.board.JP26.value():
print('lower')
print(adc.read())
stm.mem16[stm.TIM1 + stm.TIM_CR1] = 0
stm.mem16[stm.TIM2 + stm.TIM_CR1] = 0
#stm.mem16[stm.TIM5 + stm.TIM_CR1] = 0
#pyb.Pin.board.JP25.setvalue(0)
t3.callback(shutdown_timer)
#t1.deinit()
#t5.deinit()
#the_active_timer.deinit()
else:
ccer_set5()
#print(bin(stm.mem16[stm.TIM2 + stm.TIM_CCER]))
#t5.counter(0)
#cc_set5(False)
#t2.counter(xfmr_pulse_period - (half_pulse//2))
#cc_set5(False)
@micropython.asm_thumb
def set_right(r0, r1):
"TIM2_CR1_data, TIM5_CR1_data"
movwt(r2, stm.TIM2)
strh(r0, [r2, stm.TIM_CR1])
nop()
movwt(r3, stm.TIM5)
strh(r1, [r3, stm.TIM_CR1])
@micropython.native
def last():
lower.callback(disable_lower)
tim2_cr1_set(False)
upper.callback(disable_upper)
tim5_cr1_set(False)
#t2.counter()
#tim2_cr1_set()
#_nop()
#tim5_cr1_set()
lower.callback(disable_lower)
tim2_cr1_disable_clock()
# tim2_cr1_set(False)
#upper.callback(disable_upper)
tim5_cr1_disable_clock()
# tim5_cr1_set(False)
#force_inactive5()
#force_inactive()
#last()
t5.counter(0)
t2.counter(xfmr_pulse_period)
# set_right((stm.mem16[stm.TIM2 + stm.TIM_CR1] & 0b1111111111111110 )| 0b0000000000000001,
# (stm.mem16[stm.TIM5 + stm.TIM_CR1] & 0b1111111111111110 )| 0b0000000000000001,
# )
print(bin(stm.mem16[stm.TIM2+stm.TIM_CR2]))
print(bin(stm.mem16[stm.TIM5+stm.TIM_CR2]))
stm.mem16[stm.TIM2+stm.TIM_CR2]|= 1<<4
stm.mem16[stm.TIM3+stm.TIM_CR2]|= 1<<4
stm.mem16[stm.TIM5+stm.TIM_CR2]|= 1<<4
print(bin(stm.mem16[stm.TIM2+stm.TIM_CR2]))
print(bin(stm.mem16[stm.TIM5+stm.TIM_CR2]))
tim1_cr2_set()
tim2_smcr_()
tim3_smcr_()
tim5_smcr_()
tim1_cr1_set()
# Using one timer to enable another timer
# In this example, we control the enable of Timer 2 with the output compare 1 of Timer 1.
# Refer to Figure 127 for connections. Timer 2 counts on the divided internal clock only when
# OC1REF of Timer 1 is high. Both counter clock frequencies are divided by 3 by the
# prescaler compared to CK_INT (fCK_CNT = fCK_INT/3).
# • Configure Timer 1 master mode to send its Output Compare 1 Reference (OC1REF)
# signal as trigger output (MMS=100 in the TIM1_CR2 register).
# • Configure the Timer 1 OC1REF waveform (TIM1_CCMR1 register).
# • Configure Timer 2 to get the input trigger from Timer 1 (TS=000 in the TIM2_SMCR register).
# • Configure Timer 2 in gated mode (SMS=101 in TIM2_SMCR register).
# • Enable Timer 2 by writing ‘1 in the CEN bit (TIM2_CR1 register).
# • Start Timer 1 by writing ‘1 in the CEN bit (TIM1_CR1 register).
# In the next example, we synchronize Timer 1 and Timer 2. Timer 1 is the master and starts
# from 0. Timer 2 is the slave and starts from 0xE7. The prescaler ratio is the same for both
# timers. Timer 2 stops when Timer 1 is disabled by writing ‘0 to the CEN bit in the TIM1_CR1
# register:
# • Configure Timer 1 master mode to send its Output Compare 1 Reference (OC1REF)
# signal as trigger output (MMS=100 in the TIM1_CR2 register).
# • Configure the Timer 1 OC1REF waveform (TIM1_CCMR1 register).
# • Configure Timer 2 to get the input trigger from Timer 1 (TS=000 in the TIM2_SMCR register).
# • Configure Timer 2 in gated mode (SMS=101 in TIM2_SMCR register).
# • Reset Timer 1 by writing ‘1 in UG bit (TIM1_EGR register).
# • Reset Timer 2 by writing ‘1 in UG bit (TIM2_EGR register).
# • Initialize Timer 2 to 0xE7 by writing ‘0xE7’ in the timer 2 counter (TIM2_CNTL).
# • Enable Timer 2 by writing ‘1 in the CEN bit (TIM2_CR1 register).
# • Start Timer 1 by writing ‘1 in the CEN bit (TIM1_CR1 register).
# • Stop Timer 1 by writing ‘0 in the CEN bit (TIM1_CR1 register).
# Using one timer to start another timer
# In this example, we set the enable of Timer 2 with the update event of Timer 1. Refer to
# Figure 127 for connections. Timer 2 starts counting from its current value (which can be
# nonzero) on the divided internal clock as soon as the update event is generated by Timer 1.
# When Timer 2 receives the trigger signal its CEN bit is automatically set and the counter
# counts until we write ‘0 to the CEN bit in the TIM2_CR1 register. Both counter clock
# frequencies are divided by 3 by the prescaler compared to CK_INT (fCK_CNT = fCK_INT/3).
## • Configure Timer 1 master mode to send its Update Event (UEV) as trigger output (MMS=010 in the TIM1_CR2 register).
# • Configure the Timer 1 period (TIM1_ARR registers).
# • Configure Timer 2 to get the input trigger from Timer 1 (TS=000 in the TIM2_SMCR
# register).
# • Configure Timer 2 in trigger mode (SMS=110 in TIM2_SMCR register).
# • Start Timer 1 by writing ‘1 in the CEN bit (TIM1_CR1 register)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment