STM32F4计时器-计算周期和预分频比,并产生1 ms的延迟

时间:2018-08-18 08:19:22

标签: timer microcontroller stm32 stm32f4 cubemx

我将STM32F407VGT6CubeMX一起使用。
因此,我从通用计时器入手,而我却陷入了预分频和周期值的问题。

基本上我想每隔n(其中n = 1,2,3 ..)ms生成一个计时器中断并执行一些任务。
公式中有很多变化来计算期间和预分摊的价值

某些公式的版本为:

  

TIMupdateFreq(HZ)=时钟/(((PSC-1)*(Period-1))
  更新事件= TIM clk /(((PSC + 1)*(ARR + 1)*(RCR + 1))
  预分频器=((((ClockSpeed)/((period)/(1 / frequency)))+ 0.5)-1)

因此,我的核心时钟运行在168 MHz,但我可以看到计时器已连接到运行在APB1 Bus的{​​{1}}。

我尝试过一个代码,该代码会产生1 ms的延迟(作者说),在将该值用于预分频和周期后,我生成了一个代码,该代码也会产生1ms的延迟(直觉-没有作用域)。

该代码使用41999的预缩放值和1999年的时间。

因此,
PSC-41999
ARR-1999
将其应用于第二个公式

84 MHz

Update Event = TIM clk/((PSC+1)*(ARR+1)*(RCR+1))(这是1毫秒的延迟吗?)

好,现在我想了解如何选择Update Event = 84000000/(42000*2000) = 1PSC = 41999?它是否纯粹基于假设,如我使用的任何公式中我都必须假设一个变量。如果我想说1.5或2.3或4.9之类的精确计时,如何计算预分频和周期。??

编辑

此外,当我使用Period = 1999时,更新事件值为2。

PSC=41999 and Period =999

但是我的延迟是每秒两次。即500ms

当我使用Update Event = 84000000/(42000*1000) = 2时,更新事件值为0.5。

PSC=39999 and Period =4199

我的延迟是2毫秒。

预先感谢

3 个答案:

答案 0 :(得分:4)

  

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 = 41999Period = 1999

采用简单的公式

Updatefrequency = TIM clk/((PSC+1)*(ARR+1))

重新安排为

(PSC+1)*(ARR+1) = TIMclk/Updatefrequency

那么您在右手边有一个已知值,但在左手边有两个未知数。简单的解决方案是设置其中之一,例如PSC0,以及ARR至右侧值-1。

不幸的是,大多数计时器仅具有16位寄存器,因此在TIMclk/Updatefrequency > 65535时这将不起作用。 PSCARR都必须介于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。如果所需比率不是一个很好的整数,则应诉诸integer factorization,或编写一个小程序来查找所有可能的除数(for(i=0;i<65536;i++) ...)。

也有可能根本没有精确的整数解,然后您仍然可以循环遍历所有可能的预分频器值,并查看哪个误差最小。

  

Update Event = 84000000/(42000*1000) = 2

     

但是我的延迟是每秒两次。即500ms

注意尺寸。您在公式中使用频率,将84 MHz输入频率除以某些值,结果为 2 Hz 。 2 Hz频率意味着每秒发生两个事件,因此这些事件确实相距500ms。

答案 1 :(得分:1)

没有“变化”。仅存在一个公式:

Period = (PSC+1)*(ARR+1) / TmerClockFreq,以秒为单位 Period = 1000 * (PSC+1)*(ARR+1) / TmerClockFreq(以毫秒为单位)

因此,您需要找到ARR和PSC,以便为您提供尽可能接近所需时间的时间

答案 2 :(得分:1)

我认为我会在这里提出更全面的答案。对于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的商业工具一样,也只能提出一种精确(或不精确)的组合。如何找到所有这些?我只是写了一个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)

使用此程序,每个人都可以放心地计算这些值。我希望它能证明有用。