通过mem32函数来提高MM32 MicroPython 输出PWM 频率的精度

Posted 卓晴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过mem32函数来提高MM32 MicroPython 输出PWM 频率的精度相关的知识,希望对你有一定的参考价值。

简 介: 利用mem32功能,对于MM32的MicroPython中的PWM频率精度低的问题,通过重新调整ARR来提高PWM频率精度。

关键词 PWMMM32MicroPythonmem32

MM32 PWM输出 目 录
Contents
版本的优缺点 误差分析 PWM频率确定 误差 如何改进PWM
频率误差?
修改方式 修改结果 在MicroPython
实现
实现代码 测试结果 总 结 软件代码 MicroPython程序 测试代码 mm32代码

 

§01 MM32 PWM输出


1.1 版本的优缺点

  在MindMotion MM32 单片机上的MicroPython移植-PWM中给出了灵动公司SuYong移植在MM32F3277上的MicroPython版本中具有了PWM。相比于MicroPython官网给出的版本,这个版本的PWM优点:

  • 它是基于两个Timer(TIM3、TIM4)给出了八个通道的PWM输出,所以它允许存在两组不同基频的PWM波形输出。从而可以分别控制舵机、直流电机控制等。

  但在实现过程中,它的缺点也很明显。SuYong在实现过程中,对于ARR固定位999,对应PWM的CNT范围是从0 ~ 999。可以实现1/1000的输出PWM精度。但这带来对应的输出PWM频率精度受限。

  这一点在 使用MM32 MicroPython产生双音频信号的局限性 进行了测量。下图给出从500到2000Hz之内, MM32 PWM频率出现的绝对误差。

▲ 图1.1.1 输出频率在500 ~ 2000 Hz之间对应的实际PWM频率误差

1.2 误差分析

1.2.1 PWM频率确定

  假设MM32F3277的Time工作频率来自于MCU的主频,对应 f o s c = 120 M H z f_osc = 120MHz fosc=120MHz 。对于 A R R = 999 ARR = 999 ARR=999 ,确定PWM频率是由TIM3/TIM4的预分配器 PSC 来决定。

f P W M = f o s c ( 1 + P S C ) ⋅ ( A R R + 1 ) f_PWM = f_osc \\over \\left( 1 + PSC \\right) \\cdot \\left( ARR + 1 \\right) fPWM=(1+PSC)(ARR+1)fosc

  由于PSC必须采用整数,所以对应输出的 f P W M f_PWM fPWM 会存在一定的误差。

1.2.2 误差

  下面是从500 到1000 范围内设定的频率与实际频率之间的误差。

from headm import *

fset = range(500, 2000, 5)

def deltaf(f):
    fosc = 120e6
    psc = int(fosc/f/1000)-1
    freal = fosc/(1+psc)/1000

    return f-freal

fdel = [deltaf(f) for f in fset]

plt.plot(fset, fdel)

plt.xlabel("Set Frequency(Hz)")
plt.ylabel("Delta Frequency(Hz)")
plt.grid(True)
plt.tight_layout()
plt.show()

▲ 从500 - 1000 内对应的频率误差

  下面是每隔5Hz计算出来的PWM 频率误差,这与在使用MM32 MicroPython产生双音频信号的局限性中实际测量的结果基本上很接近了。

▲ 图1.2.2 500 ~ 2000Hz 之间每隔5Hz计算出的理论频率误差

1.3 如何改进PWM频率误差?

  这个问题主要来自于在SuYong的PWM功能实现过程中,固定ARR为999,这就使得实际输出的PWM频率无法进行小的调整。下面给出一个计算方式,使得ARR在999范围前后,能够根据误差进行调整,使得输出的频率满足设定的频率。

1.3.1 修改方式

  具体修改方式分为两步,有下面的 函数给出:

def deltaf(f):
    fosc = 120e6
    psc = int(fosc/f/1000)-1
    arr = int(fosc/(1+psc)/f) - 1

    freal = fosc/(1+psc)/(1+arr)

    return f-freal,arr

1.3.2 修改结果

  利用这种方式修改之后,对应的ARR在1000左右进行浮动,可以看到对应的频率误差都小于1/1000

▲ 对应的频率误差与ARR取值

1.4 在MicroPython实现

  根据MM32F3277 MicroPython的 mem 函数对于MCU内存访问描述,可以利用mem32技术直接访问MM32F3277的寄存器,所以可以将上面修正后的频率所需要对应的PSC, ARR利用Mem32进行调整。从而实现提高PWM 输出频率的精度。

1.4.1 实现代码

#------------------------------------------------------------
from micropython            import const
APB1PERIPH_BASE = const(0x40000000)
TIM3_BASE       = const(APB1PERIPH_BASE + 0x0400)
TIM4_BASE       = const(APB1PERIPH_BASE + 0x0800)
TIM_TYPE_CR1    = const(0*4)
TIM_TYPE_CR2    = const(1*4)
TIM_TYPE_SR     = const(4*4)
TIM_TYPE_CNT    = const(9*4)
TIM_TYPE_PSC    = const(10*4)
TIM_TYPE_ARR    = const(11*4)
TIM_TYPE_CCR1   = const(13*4)
TIM_TYPE_CCR2   = const(14*4)
TIM_TYPE_CCR3   = const(15*4)
TIM_TYPE_CCR4   = const(16*4)

def pwmFreq(f, pwm):
    fosc = 96e6
    psc = int(fosc/f/1000) - 1
    arr = int(fosc/(1+psc)/f) - 1

    if pwm < 4: base = TIM3_BASE
    else: base = TIM4_BASE

    mem32[base+TIM_TYPE_PSC] = psc
    mem32[base+TIM_TYPE_ARR] = arr

    return arr

#------------------------------------------------------------
pwmFreq(697, 0)
pwmFreq(697, 4)

1.4.2 测试结果

  实际测量对应的输出频率结果为 697.32Hz。

  测试设定PWM频率与实际输出频率之间的误差。为什么是这样,现在无法解释。

▲ 图1.4.1 500 到 2000Hz 之间的设置与输出频率之间的误差

  下面对于arr的取值进行调整,进行四舍五入。 另外对于ARR设置为10000左右,可以看到误差频率在10000分之一左右。

▲ 图1.4.2 频率在500-2000Hz之间的设置误差

▲ 图1.4.3 在频率 500 - 1600Hz之内的频率误差

 

  结 ※


  用mem32功能,对于MM32的MicroPython中的PWM频率精度低的问题,通过重新调整ARR来提高PWM频率精度。

2.1 软件代码

2.1.1 MicroPython程序

from machine                import Pin,mem32,PWM
import utime

led = Pin('PB2', Pin.OUT_PUSHPULL)
f = 697
pwm0 = PWM(0, freq=f, duty=500)
pwm1 = PWM(4, freq=f, duty=500)

from micropython            import const
APB2PERIPH_BASE = const(0x40010000)
UART1_BASE    = const(APB2PERIPH_BASE + 0x3800)
UART1_RDR     = const(UART1_BASE + 1*

以上是关于通过mem32函数来提高MM32 MicroPython 输出PWM 频率的精度的主要内容,如果未能解决你的问题,请参考以下文章

利用mem数组在MM32 MicroPython中实现COMP的功能

制作测试MM32F3277-MicroPython最小电路板

MindMotion MM32F3277 SoftI2C功能测试

如何用 gcc 或 clang 模拟 _mm256_loadu_epi32?

MicroPython内核开发笔记书内软件用例 :MEM相关实验用例

MySql crc32&&crc64函数提高字符串查询效率