jcky001 发表于 2022-8-18 10:01

MM32SPIN2x 电机专用MCU功能特色——硬件除法器与硬件开方

       上一章节中已经教大家如何使用MM32SPIN2x的PWM控制模控制功能,本章节将与大家一起配置硬件除法器和硬件开方器。
      除法和开方是非常消耗时间的运算,而在电机控制算法中,乘除法和平方根运算在电机运算中使用频率较高。为了提高MCU的工作效率,MM32SPIN2x了内嵌硬件32bit硬件除法器和32bit硬件乘法器,能自动执行有符号或32位整数乘除法和开根号运算。硬件运算大大提升了应用程序的效率,减少了代码运算量,相比软件它们对于特定问题计算速度更快,位宽更大。
       下面和大家一起配置如何使用硬件除法器和硬件开方进行运算。
      硬件除法单元包括六个32位寄存器,四个数据寄存器分别为被除数、除数、商和余数,以及一个控制寄存器和一个状态寄存器。在使用时,先打开硬件除法器时钟使能,然后配置控制寄存器(HWDIV_CR)选择是否使能除零溢出中断和有无符号除法,然后往被除数寄存器和除数寄存器中写入数据,每一次写入除数寄存器,会自动触发除法运算,在运算结束后,结果会写入到商和余数寄存器里。如果在运算未结束前读商寄存器、余数寄存器或者状态寄存器,读操作会被暂停,直到运算结束才会返回运算结果。特别的,如果除数为零,会产生溢出中断标志位。寄存器详细定义请参考MM32SPIN2x_p用户手册。

jcky001 发表于 2022-8-18 10:01

硬件除法器初始化配置如下:
RCC_AHBPeriphclockCmd(RCC_AHBPeriph_HWDIV, ENABLE); //使能除法器时钟
HWDIV->DIVCON |= (DIV_UNSIGN );//无符号除法,不使能除零中断

为了验证硬件除法器的效率,在主函数中分别使用硬件除法器和软件除法器进行16次除法运算,不使用while是为了避免多余的指令占用时间。
主函数如下:



[*]u32 DVD_data = {
[*]0x12345678,0x9876554 ,0x9822346 ,0x98734662,
[*]0x000001 ,0xFFFFFFFF,0x11111111,0x22222222,
[*]0x33333333,0x78645323,0x4399039 ,0x4367464 ,
[*]0x42345678,0x9873554 ,0x9822346 ,0x98734662,
[*]0x100001 ,0x1FFFFFFF,0x11511111,0x22422222,
[*]0x53333333,0x78645323,0x4399039 ,0x4367464 ,
[*]0x140001 ,0x11FFFFFF,0x12111111,0x29422222,
[*]0x53333333,0x78644323,0x4369039 ,0x4767464 ,
[*]};
[*]u32 DVS_data = {
[*]0x11,0x22,0x33,0x44,
[*]0x55,0x66,0x77,0x88,
[*]0x99,0xaa,0xbb,0xcc,
[*]0xdd,0xee,0xff,0xee,
[*]0xdd,0xcc,0xbb,0xaa,
[*]0x99,0x88,0x77,0x66,
[*]0x55,0x44,0x33,0x22,
[*]0x11,0x22,0x33,0x44,
[*]};//除数数组
[*]u32 result;
[*]int main (void)
[*]{
[*]u32 i ;
[*]IO_Init();
[*]RCC_AHBPeriphClockCmd(RCC_AHBPeriph_HWDIV, ENABLE);
[*]HWDivider_UnsignInit();
[*]while(1)
[*]{
[*]GPIOB->ODR ^= 1<<5;
[*]GPIOB->ODR ^= 1<<5;
[*]//硬件除法器运算
[*]SET_HWDivider(DVD_data,DVS_data);
[*]result = GET_HWDivider;
[*]SET_HWDivider(DVD_data,DVS_data);
[*]result = GET_HWDivider;
[*]SET_HWDivider(DVD_data,DVS_data);                                                            result = GET_HWDivider;
[*]SET_HWDivider(DVD_data,DVS_data);
[*]result = GET_HWDivider;
[*]SET_HWDivider(DVD_data,DVS_data);
[*]result = GET_HWDivider;
[*]SET_HWDivider(DVD_data,DVS_data);
[*]result = GET_HWDivider;
[*]SET_HWDivider(DVD_data,DVS_data);
[*]result = GET_HWDivider;
[*]SET_HWDivider(DVD_data,DVS_data);
[*]result = GET_HWDivider;
[*]SET_HWDivider(DVD_data,DVS_data);
[*]result = GET_HWDivider;
[*]SET_HWDivider(DVD_data,DVS_data);
[*]result = GET_HWDivider;
[*]SET_HWDivider(DVD_data,DVS_data);
[*]result = GET_HWDivider;
[*]SET_HWDivider(DVD_data,DVS_data);
[*]result = GET_HWDivider;
[*]SET_HWDivider(DVD_data,DVS_data);
[*]result = GET_HWDivider;
[*]SET_HWDivider(DVD_data,DVS_data);
[*]result = GET_HWDivider;
[*]SET_HWDivider(DVD_data,DVS_data);
[*]result = GET_HWDivider;
[*]SET_HWDivider(DVD_data,DVS_data);
[*]result = GET_HWDivider;
[*]GPIOB->ODR ^= 1<<5;
[*]GPIOB->ODR ^= 1<<5;
[*]i = 1000;while(i--);
[*]GPIOB->ODR ^= 1<<5;
[*]GPIOB->ODR ^= 1<<5;
[*]//软件除法器运算
[*]result = DVD_data/DVS_data;
[*]result = DVD_data/DVS_data;
[*]result = DVD_data/DVS_data;
[*]result = DVD_data/DVS_data;
[*]result = DVD_data/DVS_data;
[*]result = DVD_data/DVS_data;
[*]result = DVD_data/DVS_data;
[*]result = DVD_data/DVS_data;
[*]result = DVD_data/DVS_data;
[*]result = DVD_data/DVS_data;
[*]result = DVD_data/DVS_data;
[*]result = DVD_data/DVS_data;
[*]result = DVD_data/DVS_data;
[*]result = DVD_data/DVS_data;
[*]result = DVD_data/DVS_data;
[*]result = DVD_data/DVS_data;
[*]GPIOB->ODR ^= 1<<5;
[*]GPIOB->ODR ^= 1<<5;
[*]i = 1000;while(i--);
[*]}
[*]}

复制代码

jcky001 发表于 2022-8-18 10:03

硬件除法器进行16次除法运算用时6.52us(96MHz):


图1 硬件除法器32次除法运算软件进行32次除法运算用时42.29us(96MHz):

图2 软件32次除法运算


jcky001 发表于 2022-8-18 10:03

开方运算在电机控制里面也非常常见,例如矢量合成和滤波部分。MM32SPIN2x系列自带硬件开方器支持32位无符号整数的开平方。
       硬件开方器包括1个32位被开方寄存器和1个16位的平方根寄存器,都是无符号整数。每一次写入被开方寄存器,会自动除法开方运算,在运算结束后,结果会写入到平方根寄存器里。如果在结束前读平方根寄存器,读操作会被暂停,直到结束才返回运算结果。
      硬件开方器的配置极其简单,只需打开硬件开方器的时钟后,在运算时写入被开方数即可。软件运算使用C语言自带的math.h中的sqrt()开平方函数。



[*]u32 HWROOT_data = {
[*]0x12345678,0x9876554 ,0x9822346 ,0x98734662,
[*]0x000001,0xFFFFFFFF,0x11111111,0x22222222,
[*]0x33333333,0x78645323,0x4399039 ,0x4367464 ,
[*]0x42345678,0x9873554 ,0x9822346 ,0x98734662,
[*]0x100001,0x1FFFFFFF,0x11511111,0x22422222,
[*]0x53333333,0x78645323,0x4399039 ,0x4367464 ,
[*]0x140001,0x11FFFFFF,0x12111111,0x29422222,
[*]0x53333333,0x78644323,0x4369039 ,0x4767464 ,
[*]};//被开方数数组
[*]u32 result; //商和余数
[*]int main (void)
[*]{
[*]u32 i ;
[*]IO_Init();
[*]RCC_AHBPeriphClockCmd(RCC_AHBPeriph_HWROOT,ENABLE);
[*]while(1)
[*]{
[*]GPIOB->ODR ^= 1<<5;
[*]GPIOB->ODR ^= 1<<5;
[*]//硬件开方运算
[*]HWROOT->SQR = HWROOT_data;
[*]result = HWROOT->ROOT;
[*]HWROOT->SQR = HWROOT_data;
[*]result = HWROOT->ROOT;
[*]HWROOT->SQR = HWROOT_data;
[*]result = HWROOT->ROOT;
[*]HWROOT->SQR = HWROOT_data;
[*]result = HWROOT->ROOT;
[*]HWROOT->SQR = HWROOT_data;
[*]result = HWROOT->ROOT;
[*]HWROOT->SQR = HWROOT_data;
[*]result = HWROOT->ROOT;
[*]HWROOT->SQR = HWROOT_data;
[*]result = HWROOT->ROOT;
[*]HWROOT->SQR = HWROOT_data;
[*]result = HWROOT->ROOT;
[*]HWROOT->SQR = HWROOT_data;
[*]result = HWROOT->ROOT;
[*]HWROOT->SQR = HWROOT_data;
[*]result = HWROOT->ROOT;
[*]HWROOT->SQR = HWROOT_data;
[*]result = HWROOT->ROOT;
[*]HWROOT->SQR = HWROOT_data;
[*]result = HWROOT->ROOT;
[*]HWROOT->SQR = HWROOT_data;
[*]result = HWROOT->ROOT;
[*]HWROOT->SQR = HWROOT_data;
[*]result = HWROOT->ROOT;
[*]HWROOT->SQR = HWROOT_data;
[*]result = HWROOT->ROOT;
[*]HWROOT->SQR = HWROOT_data;
[*]result = HWROOT->ROOT;
[*]GPIOB->ODR ^= 1<<5;
[*]GPIOB->ODR ^= 1<<5;
[*]i = 1000;while(i--);
[*]
[*]GPIOB->ODR ^= 1<<5;
[*]GPIOB->ODR ^= 1<<5;
[*]result = sqrt(HWROOT_data);//软件开方运算
[*]result = sqrt(HWROOT_data);
[*]result = sqrt(HWROOT_data);
[*]result = sqrt(HWROOT_data);
[*]result = sqrt(HWROOT_data);
[*]result = sqrt(HWROOT_data);
[*]result = sqrt(HWROOT_data);
[*]result = sqrt(HWROOT_data);
[*]result = sqrt(HWROOT_data);
[*]result = sqrt(HWROOT_data);
[*]result = sqrt(HWROOT_data);
[*]result = sqrt(HWROOT_data);
[*]result = sqrt(HWROOT_data);
[*]result = sqrt(HWROOT_data);
[*]result = sqrt(HWROOT_data);
[*]result = sqrt(HWROOT_data);
[*]GPIOB->ODR ^= 1<<5;
[*]GPIOB->ODR ^= 1<<5;
[*]i = 1000;while(i--);
[*]}
[*]}

复制代码

jcky001 发表于 2022-8-18 10:05

硬件开方器执行16次开方运算用时5.44us(96MHz):


图三 硬件开方32次开方运算软件执行16次开方运算用时238.22us(96MHz):

图四 软件32次开方运算      由此可见,硬件除法器和硬件开方在提升运算速度,降低MCU负担方面有极其显著的作用。


tpgf 发表于 2022-9-3 18:58

纯硬件的除法器吗

qcliu 发表于 2022-9-3 19:15

开平方会不会导致程序运行缓慢啊

drer 发表于 2022-9-3 19:20

这种运算对单片机的位数有要求吗

coshi 发表于 2022-9-3 19:25

可以外挂这种专用芯片吗

kxsi 发表于 2022-9-3 19:35

这种芯片还是很有优势的

wiba 发表于 2022-9-3 20:06

感觉这种代码的风格不太好

abotomson 发表于 2022-9-5 13:01

可以提供计算的速度吗

ccook11 发表于 2022-9-5 15:30

计算的速度可以提高多少?

kmzuaz 发表于 2022-9-5 17:31

如何确定使用的是硬件除法呢?

Bowclad 发表于 2022-9-9 19:05

开平方会不会导致程序运行缓慢啊
页: [1]
查看完整版本: MM32SPIN2x 电机专用MCU功能特色——硬件除法器与硬件开方