wkhn
认证:优质创作者
所在专题目录 查看专题
通向数字电源之路——初学者入门(3)
通向数字电源之路——初学者入门(4)
通向数字电源之路——初学者入门(5)
通向数字电源之路--进阶(1)
通向数字电源之路--进阶(2)
通向数字电源之路--进阶(3)
作者动态 更多
一种采用CAN总线方式升级F28035芯片Flash的方法(三)
05-13 15:31
一种采用CAN总线方式升级F28035芯片Flash的方法(二)
05-13 15:31
一种采用CAN总线方式升级F28035芯片Flash的方法(一)
05-13 15:31
STM32G4系列MCU——数字电源入门(4)
2023-03-14 10:46
STM32G4系列MCU——数字电源入门(3)
2023-03-13 20:05

通向数字电源之路--进阶(2)

      在数字电源的研发过程中,纯数字控制的闭环算法是个难点。要想达到预期的性能指标,一般要求控制环中的算法满足下面的一些条件:

1.从被控量的采样到完成占空比的计算和更新,这个过程的时间要尽可能的短。越少的时间越能提高控制环路的相位裕度,增加环路的稳定性。针对这个问题,microchip的dsp系列单片机有专用的硬件来解决。以dsp33ep128gs806举例:

      首先,为缩短ADC采样的时间,该芯片内部有4个专用内核用来对被控量进行采样,以最高速运行的dsp,adc的转换时间能控制在200ns以内。在上篇文章中,用来采样mos电流和输入输出电压的ADC(AN0、AN1、AN2、AN3)都是专用内核。

      其次,为减少进入ADC中断时,寄存器压栈和出栈的时间,引入context转换的功能。笔者实测能比普通方式进入ADC中断少300ns左右。

      最后,为了快速解算环路中差分方程的解,引入带饱和功能的40位累加器,在一个指令周期能完成累加,相乘,两个参数的读取,累加器回写等指令。配合专用的累加器汇编指令,能加快运算速度。以笔者用的PID算法,在60MHz的工作频率下,能在1.6us的时间内完成差分方程的求解和占空比的更新。

2.环路中的差分方程的参数有很多是用小数表示的。为了满足控制的精度,并且还能有很快的运算速度,microchip的dsp33ep系列的dsp单片机没有用浮点数表示小数,而是用定点数来表示。具体到累加器中的小数表示,就是用Q15的格式。

      从上面提到的这些条件来看,笔者觉得,先将累加器是如何工作,如何进行小数乘法的计算这两方面弄清楚是很有必要的。

      dsp如何表示小数?dsp小数数据表示为二进制补码数,其中最高位定义为符号位,小数点隐含于符号位之后。这种格式通常被 称为1.15(或Q15)格式。其中1是用来表示数据的整数部分的位数,而15是用来表示小数部分的位数。1.15格式的dsp小数数据表示的范围是:-1.0(0x8000)至0.999969482(0x7FFF)。可见,要把纸面中的小于1的小数转换成dsp能识别的小数数据,应该用公式:,比如:

而32767的十六进制数为0x7FFF

那么0.1953125该如何表示?

6400的十六进制数为0x1900。

下面举例说明累加器如何计算小数乘法:

  • 纯小数×整数:

0.1953125*2762=??

0.1953125--0.1953125*2^15=6400--0x1900

2762--0x0ACA

下图是累加器ACCA计算乘法的过程:

将0x1900赋值给w4寄存器,0x0ACA赋值给w5寄存器。mac指令是用累加器A做w4×w5的运算,并将累加器的ACCAH部分保存在w6寄存器中,下图是40位累加器寄存器的结构图:

ACCA寄存器的结果是0x00021B7400,只保存0x021B到w6中,0x021B的十进制为539。

,所以w6的结果就是w4×w5的最终结果。其实这个计算过程手动推导一下是这样的:

而0x00010DBA00除就是右移15位,也就是0x021B,即为539。

那这个0x00010DBA00是怎么回事??其实累加器有两种工作模式:小数模式和整数模式。当处于小数模式时,会把结果自动左移一位,而整数模式工作时,则不会进行位移。所以读者可以尝试将0x00010DBA00左移一位就是0x00021B7400,因此要把0x00021B7400右移16位才是乘法运算正确的结果。而w6寄存器中的数据0x021B正是0x00021B7400右移16位的结果。

那为何小数模式会把结果自动左移一位?小数都是用1.15格式,1.15×1.15=2.30,即小数乘法的结果是2.30格式,但是累加器的小数点固定在31位和30位之间,为了对齐结果,就变成了左移一位,成为1.31格式。

从上面的分析中,可以看到,对于累加器A来说,根本就没有做小数的乘法,都是整数的乘法,小数点只存在于程序员的心里。

  • 纯小数乘纯小数:

0.1953125*0.08428955078125=??

0.01953125--0.01953125*2^15=6400--0x1900

0.08428955078125--0.08428955078125*2^15=2762--0x0ACA

0.1953125*0.08428955078125=0.01646280288.......

考虑到小数取整时的误差,可以看出,累加器的计算结果在一定精度上是对的!!

  • 整数乘整数:(用累加器的整数模式)

6400*2762=17676800(十六进制0x00010DBA00)

这时的正确结果是保存在ACCxH和ACCxL两个寄存器中,无法把结果保存在一个16位的寄存器中。

  • 大于1的小数×整数:

以上都是对于纯小数或纯整数的乘法做的计算。那么对于大于1的小数该如何表示?大于1的小数无法表示成1.15的格式!

还是那句话,小数点只存于使用者的心里,累加器只会做整数的乘法!

举例:

3.348*2762=9247.176

3.348是大于1的小数,且小于4(2^2),所以换算成dsp可以识别的小数就应该左移(15-2)位,即13位。

2762--0x0ACA

w6寄存器保存正确的结果0x241F--十进制为9247。

手动推导计算过程:

在计算完w4×w5的结果后,还要用sftac指令将累加器结果寄存器ACCA左移2位,最终保存在w6寄存器才是正确的结果。

在microchip官方提供的PID算法库函数中,对于大于1的小数就是用这种方法来计算的,这在后面还会提到。

通过前面的几个例子,可以看到dsp能够处理任意小数的乘法运算。但是要注意结果饱和的问题。比如:

200.863*742=149040.346 > 32767,

这时再用上面的步骤,得到结果后,再左移位,将会引起累加器的饱和,这种情况就只能用整数模式,并且自己计算小数的位移,保存计算结果。

200.863<256(2^8)所以左移7位。即

742--十六进制0x02E6

可以看到累加器最终的计算结果为0x00012316D4,这时就不能再左移8位了,否则会导致累加器ACCA饱和

最终结果与正确的结果有一定的误差,这是由于取整误差造成的。

总结:

      dsp的小数乘法,本质上就是整数乘法,当对于累加器的工作方式了解以后,有助于程序员选择合适的计算模式。

      通过上面的方法,dsp对所有整数和小数的乘法运算都可以很好的支持,明白这些之后,才能熟练应用smps_control_library函数库,明白如何设定函数的参数。

声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
觉得内容不错的朋友,别忘了一键三连哦!
赞 8
收藏 6
关注 518
成为作者 赚取收益
全部留言
0/200
  • dy-pGz7c8Dn 2022-03-18 23:46
    跟着大师学!
    回复
  • zhoucwyh 2021-12-15 22:17
    跟着大师学!
    回复
  • 星球官方号 2021-11-27 16:44
    点赞(。ò ∀ ó。)
    回复
  • Westbrook 2021-11-25 10:57
    跟着大师学!
    回复