_STM32F407VGT6
_とCubeMX
を使用しています。
それで私は汎用タイマーから始めていて、プリスケールと期間の値で立ち往生しています。
基本的に、n
(n = 1,2,3 ..)msごとにタイマー割り込みを生成し、いくつかのタスクを実行したいと思います。
周期とプリスケールの値を計算する式には多くのバリエーションがあります
式の一部のバージョンは次のとおりです。
TIMupdateFreq(HZ)= Clock /((PSC-1)*(Period-1))
更新イベント= TIM clk /((PSC + 1)*(ARR + 1)*(RCR + 1))
プリスケーラ=(((((ClockSpeed)/((period)/(1/frequency)))+ 0.5)-1)
質問に来ると、コアクロックは_168 MHz
_で実行されていますが、タイマーが_APB1 Bus
_で実行されている_84 MHz
_に接続されていることがわかります。
私は1ミリ秒の遅延を生成するコードを試してみました(著者によると)その値をプリスケールと期間に使用した後、1ミリ秒の遅延を生成するコード(直感-スコープなし)も生成しました。
コードでは、41999のプリスケール値と1999の期間を使用しています。
そう、
PSC-41999
ARR-1999
これを2番目の式に適用
Update Event = TIM clk/((PSC+1)*(ARR+1)*(RCR+1))
Update Event = 84000000/(42000*2000) = 1
(これは1msの遅延ですか?)
わかりましたので、今、この_PSC = 41999
_と_Period = 1999
_がどのように選択されているかを理解しようとしていますか?それは純粋に仮定に基づいていますか? 1.5または2.3または4.9で正確なタイミングのようなものを言いたい場合、プリスケールと周期を計算する方法は?
[〜#〜]編集[〜#〜]
さらに、_PSC=41999 and Period =999
_を使用した場合、更新イベントの値は2です。
Update Event = 84000000/(42000*1000) = 2
しかし、私の遅延は毎秒2回です。つまり、500ms
また、_PSC=39999 and Period =4199
_を使用する場合、更新イベントの値は0.5です。
Update Event = 84000000/(40000*4200) = 0.5
と私の遅延2ミリ秒。
前もって感謝します
TIMupdateFreq(HZ)= Clock /((PSC-1)*(Period-1))
これは明らかに間違っています。カウンターは0からレジスター値(両端を含む)まで進み、レジスター値よりも常に1サイクル多く、1サイクルではありません。
更新イベント= TIM clk /((PSC + 1)*(ARR + 1)*(RCR + 1))
これの方が優れていますが、汎用タイマーにはRCR
レジスタがありません。 _RCR=0
_を想定し、数式から*(RCR+1)
を省略できます。
プリスケーラ=((((ClockSpeed)/((period)/(1/frequency)))+ 0.5)-1)
これは、整数解が不可能な場合に結果を丸めようとします。後で詳しく説明します。
Update Event = 84000000/(42000*2000) = 1
(これは1msの遅延ですか?)
いいえ、これは1秒(1秒)の遅延、つまり1 Hzの周波数です。
この_
PSC = 41999
_および_Period = 1999
_の選択方法
簡単な式を考えてみましょう。
_Updatefrequency = TIM clk/((PSC+1)*(ARR+1))
_
それを再配置する
_(PSC+1)*(ARR+1) = TIMclk/Updatefrequency
_
すると、右側には既知の値がありますが、左側には2つの未知数があります。簡単な解決策は、それらの1つを設定することです。 PSC
から_0
_へ、およびARR
から右側の値-1へ。
残念ながらほとんどのタイマーは16ビットのレジスターしか持っていないので、これは_TIMclk/Updatefrequency > 65535
_の場合は機能しません。 PSC
とARR
はどちらも0〜65535の範囲内でなければなりません。これらを満たす分解を見つける必要があります制約。
例を見てみましょう。2.3秒の遅延が必要です。 2.3sは周波数ではなく周期なので、式にその逆数を入れる必要があることに注意してください。
_(PSC+1) * (ARR+1) = 84000000 / (1 / 2.3) = 84000000 * 2.3 = 193200000
_
幸いなことに、最後にはゼロがたくさんあります。たとえば、プリスケーラとして_10000
_(_PSC=9999
_)、およびARR
は_19320-1 = 19319
_になります。望ましい比率がナイスラウンド数でない場合は、 整数因数分解 に頼るか、小さなプログラムを記述してすべての可能な除数(for(i=0;i<65536;i++) ...
)を探す必要があります。
また、正確な整数解がまったくない場合もあります。その場合は、可能なすべてのプリスケーラー値をループして、どれが最小のエラーを与えるかを確認できます。
Update Event = 84000000/(42000*1000) = 2
しかし、私の遅延は毎秒2回です。つまり、500ms
寸法に注意してください。式で周波数を使用しており、84 MHzの入力周波数をいくつかの値で除算し、2 Hzを結果。 2 Hzの周波数は、毎秒2つのイベントを意味するため、イベントは実際に500ミリ秒離れています。
「バリエーション」はありません。数式は1つだけ存在します:
Period = (PSC+1)*(ARR+1) / TmerClockFreq
秒単位Period = 1000 * (PSC+1)*(ARR+1) / TmerClockFreq
ミリ秒単位
したがって、必要な期間にできるだけ近い時間を提供するARRとPSCを見つける必要があります。
ここでもっと包括的な答えを投げると思いました。 84MHzクロックの場合、多数プリスケーラーと周期の組み合わせが機能します。以下はほんの一部です。
PSC ARR F ERROR EXACT
1 41999 1000.000000 0.0000000000 YES
2 27999 1000.000000 0.0000000000 YES
3 20999 1000.000000 0.0000000000 YES
4 16799 1000.000000 0.0000000000 YES
5 13999 1000.000000 0.0000000000 YES
6 11999 1000.000000 0.0000000000 YES
7 10499 1000.000000 0.0000000000 YES
9 8399 1000.000000 0.0000000000 YES
11 6999 1000.000000 0.0000000000 YES
13 5999 1000.000000 0.0000000000 YES
14 5599 1000.000000 0.0000000000 YES
15 5249 1000.000000 0.0000000000 YES
19 4199 1000.000000 0.0000000000 YES
これらをどうやって思いつくのですか? MikroElektronicaのような市販のツールでさえ、正確な(または不正確な)組み合わせは1つしかありません。それらをすべて見つける方法は?私は単にpythonプログラムを記述してすべてを計算します。それぞれを正確に分類するか、不正確なものの相対誤差を記録します。プログラムの上部で許容誤差を変更することにより、必要に応じて、計算を「締める」または「緩める」。
プログラム全体を次に示します。
import numpy as np
import pandas as pd
TARGET_F = 1000 # In Hz so 50.0 is 0.020 seconds period and 0.25 is 4 seconds period
CLOCK_MCU = 84000000
TOLERANCE = 0.0001
# -----------------------------------------------------
def abs_error(num1, num2):
return abs((num1 - num2) / num1)
def hertz(clock, prescaler, period):
f = clock / (prescaler * period)
return f
def perfect_divisors():
exacts = []
for psc in range(1, 65536):
arr = CLOCK_MCU / (TARGET_F * psc)
if CLOCK_MCU % psc == 0:
if arr <= 65536:
exacts.append(psc)
return exacts
def add_exact_period(prescaler):
entries = []
arr = CLOCK_MCU / (TARGET_F * prescaler)
if arr == int(arr):
entry = [prescaler, arr, TARGET_F, 0.0]
entries.append(entry)
return entries
def possible_prescaler_value():
possibles = []
for psc in range(1, 65536):
if psc in exact_prescalers:
continue
h1 = hertz(CLOCK_MCU, psc, 1)
h2 = hertz(CLOCK_MCU, psc, 65536)
if h1 >= TARGET_F >= h2:
possibles.append(psc)
return possibles
def close_divisor(psc, tolerance):
arr = CLOCK_MCU / (TARGET_F * psc)
error = abs_error(int(arr), arr)
if error < tolerance and arr < 65536.0:
h = hertz(CLOCK_MCU, psc, int(arr))
return psc, int(arr), h, error
else:
return None
# ------------------------------------------------------------------------
# Make a dataframe to hold results as we compute them
df = pd.DataFrame(columns=['PSC', 'ARR', 'F', 'ERROR'], dtype=np.double)
# Get exact prescalars first.
exact_prescalers = perfect_divisors()
exact_values = []
for index in range(len(exact_prescalers)):
rows = add_exact_period(exact_prescalers[index])
for rowindex in range(len(rows)):
df = df.append(pd.DataFrame(np.array(rows[rowindex]).reshape(1, 4), columns=df.columns))
# Get possible prescalers.
poss_prescalers = possible_prescaler_value()
close_prescalers = []
for index in range(len(poss_prescalers)):
value = close_divisor(poss_prescalers[index], TOLERANCE)
if value is not None:
close_prescalers.append((value[0], value[1], value[2], value[3]))
df = df.append(pd.DataFrame(np.array(close_prescalers).reshape(len(close_prescalers), 4), columns=df.columns))
# Adjust PSC and ARR values by -1 to reflect the way you'd code them.
df['PSC'] = df['PSC'] - 1
df['ARR'] = df['ARR'] - 1
# Sort first by errors (zeroes and lowest errors at top of list, and
# then by prescaler value (ascending).
df = df.sort_values(['ERROR', 'PSC'])
# Make and populate column indicating if combination is exact.
df['EXACT'] = pd.Series("?", index=df.index)
df['EXACT'] = np.where(df['ERROR'] == 0.0, "YES", "NO")
# Format for output.
df['PSC'] = df['PSC'].map('{:.0f}'.format)
df['ARR'] = df['ARR'].map('{:.0f}'.format)
df['F'] = df['F'].map('{:.6f}'.format)
df['ERROR'] = df['ERROR'].map('{:.10f}'.format)
output = df.to_string()
print(output)
print()
print('these are the ', df.shape[0], ' total combination meeting your tolerance requirement')
exit(0)
このプログラムを使用すると、誰もが自信を持ってこれらの値を計算することができます。お役に立てば幸いです。