Ehs*_*bib 3 microcontroller timer stm32 stm32f4 cubemx
我使用STM32F407VGT6
带CubeMX
。
因此,我从通用计时器开始,但始终陷于预分频和周期值。
基本上我想每隔n
(其中n = 1,2,3 ..)ms 生成一个计时器中断并执行一些任务。
公式中有很多变化,可以计算周期和预分摊的值
公式的某些版本是:
TIMupdateFreq(HZ)=时钟/(((PSC-1)*(Period-1))
更新事件= TIM clk /(((PSC + 1)*(ARR + 1)*(RCR + 1))
预分频器=((( (时钟速度)/((周期)/(1 /频率)))+ 0.5)-1)
因此,我的核心时钟运行在,168 MHz
但我可以看到定时器连接到APB1 Bus
,它正在运行84 MHz
。
我尝试了一个代码,该代码会产生1 ms的延迟(作者说),在使用该值进行预分频和周期后,我生成了一个代码,该代码也会产生1ms的延迟(直觉-无作用域)。
该代码使用的预分度值为41999,期限为1999。
因此,
PSC-41999
ARR-1999将
其应用于第二个公式
Update Event = TIM clk/((PSC+1)*(ARR+1)*(RCR+1))
Update Event = 84000000/(42000*2000) = 1
(这是1毫秒的延迟吗?)
行,所以我现在想了解如何PSC = 41999
与Period = 1999
选择?它是否纯粹基于假设,如我使用的任何公式中我都必须假设一个变量。如果我想说1.5或2.3或4.9之类的精确计时,如何计算预分频和周期?
编辑
而且,当我使用PSC=41999 and Period =999
更新事件值为2时。
Update Event = 84000000/(42000*1000) = 2
但是我的延迟是每秒两次。即500ms
当我使用时PSC=39999 and Period =4199
,更新事件值为0.5。
Update Event = 84000000/(40000*4200) = 0.5
和我的延迟2毫秒。
提前致谢
TIMupdateFreq(HZ)=时钟/(((PSC-1)*(Period-1))
这显然是错误的。计数器从0到寄存器值(含),总是比寄存器值多一个周期,而不是少一个。
更新事件= TIM clk /(((PSC + 1)*(ARR + 1)*(RCR + 1))
这个比较好,但是通用定时器没有RCR
寄存器。您可以假设RCR=0
,并*(RCR+1)
从公式中省略。
预分频器=((((ClockSpeed)/((period)/(1 /频率)))+ 0.5)-1)
当没有整数解时,这将尝试舍入结果。稍后再讨论。
Update Event = 84000000/(42000*2000) = 1
(这是1毫秒的延迟吗?)
不,这是一秒(1s)延迟或1 Hz频率。
如何
PSC = 41999
和Period = 1999
选择?
用简单的公式,
Updatefrequency = TIM clk/((PSC+1)*(ARR+1))
Run Code Online (Sandbox Code Playgroud)
重新排列为
(PSC+1)*(ARR+1) = TIMclk/Updatefrequency
Run Code Online (Sandbox Code Playgroud)
那么您在右侧有一个已知值,但在左侧有两个未知数。最简单的解决方案是将其中之一设置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
但是我的延迟是每秒两次。即500ms
注意尺寸。您在公式中使用频率,将84 MHz输入频率除以某些值,结果为2 Hz。2 Hz频率意味着每秒发生两个事件,因此这些事件确实相距500ms。
没有“变化”。只有一个公式存在:
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
Run Code Online (Sandbox Code Playgroud)
我如何想出这些?即使像 MikroElektronica 这样的商业工具也只能提供一种精确(或不精确)的组合。如何找到它们?我只是写了一个 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)
Run Code Online (Sandbox Code Playgroud)
使用这个程序,每个人都可以自信地计算这些值。我希望它证明是有用的。
归档时间: |
|
查看次数: |
9009 次 |
最近记录: |