` 本帖最后由 MMCU5721167 于 2018-11-30 09:29 编辑
来源 灵动微电MMCU
上一章节中已经教大家如何使用MM32SPIN2x的PWM控制模控制功能,本章节将与大家一起配置硬件除法器和硬件开方器。
除法和开方是非常消耗时间的运算,而在电机控制算法中,乘除法和平方根运算在电机运算中使用频率较高。为了提高MCU的工作效率,MM32SPIN2x了内嵌硬件32bit硬件除法器和32bit硬件乘法器,能自动执行有符号或32位整数乘除法和开根号运算。硬件运算大大提升了应用程序的效率,减少了代码运算量,相比软件它们对于特定问题计算速度更快,位宽更大。
下面和大家一起配置如何使用硬件除法器和硬件开方进行运算。
硬件除法单元包括六个32位寄存器,四个数据寄存器分别为被除数、除数、商和余数,以及一个控制寄存器和一个状态寄存器。在使用时,先打开硬件除法器时钟使能,然后配置控制寄存器(HWDIV_CR)选择是否使能除零溢出中断和有无符号除法,然后往被除数寄存器和除数寄存器中写入数据,每一次写入除数寄存器,会自动触发除法运算,在运算结束后,结果会写入到商和余数寄存器里。如果在运算未结束前读商寄存器、余数寄存器或者状态寄存器,读操作会被暂停,直到运算结束才会返回运算结果。特别的,如果除数为零,会产生溢出中断标志位。寄存器详细定义请参考MM32SPIN2x_p用户手册。
硬件除法器初始化配置如下:
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_HWDIV, ENABLE); //使能除法器时钟
HWDIV->DIVCON |= (DIV_UNSIGN ); //无符号除法,不使能除零中断
为了验证硬件除法器的效率,在主函数中分别使用硬件除法器和软件除法器进行16次除法运算,不使用while是为了避免多余的指令占用时间。
主函数如下:
- u32 DVD_data[32] = {
- 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[32] = {
- 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[32];
- 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[0],DVS_data[0]);
- result[0] = GET_HWDivider;
- SET_HWDivider(DVD_data[1],DVS_data[1]);
- result[1] = GET_HWDivider;
- SET_HWDivider(DVD_data[2],DVS_data[2]); result[2] = GET_HWDivider;
- SET_HWDivider(DVD_data[3],DVS_data[3]);
- result[3] = GET_HWDivider;
- SET_HWDivider(DVD_data[4],DVS_data[4]);
- result[4] = GET_HWDivider;
- SET_HWDivider(DVD_data[5],DVS_data[5]);
- result[5] = GET_HWDivider;
- SET_HWDivider(DVD_data[6],DVS_data[6]);
- result[6] = GET_HWDivider;
- SET_HWDivider(DVD_data[7],DVS_data[7]);
- result[7] = GET_HWDivider;
- SET_HWDivider(DVD_data[8],DVS_data[8]);
- result[8] = GET_HWDivider;
- SET_HWDivider(DVD_data[9],DVS_data[9]);
- result[9] = GET_HWDivider;
- SET_HWDivider(DVD_data[10],DVS_data[10]);
- result[10] = GET_HWDivider;
- SET_HWDivider(DVD_data[11],DVS_data[11]);
- result[11] = GET_HWDivider;
- SET_HWDivider(DVD_data[12],DVS_data[12]);
- result[12] = GET_HWDivider;
- SET_HWDivider(DVD_data[13],DVS_data[13]);
- result[13] = GET_HWDivider;
- SET_HWDivider(DVD_data[14],DVS_data[14]);
- result[14] = GET_HWDivider;
- SET_HWDivider(DVD_data[15],DVS_data[15]);
- result[15] = GET_HWDivider;
- GPIOB->ODR ^= 1<<5;
- GPIOB->ODR ^= 1<<5;
- i = 1000;while(i--);
- GPIOB->ODR ^= 1<<5;
- GPIOB->ODR ^= 1<<5;
- //软件除法器运算
- result[0] = DVD_data[0]/DVS_data[0];
- result[1] = DVD_data[1]/DVS_data[1];
- result[2] = DVD_data[2]/DVS_data[2];
- result[3] = DVD_data[3]/DVS_data[3];
- result[4] = DVD_data[4]/DVS_data[4];
- result[5] = DVD_data[5]/DVS_data[5];
- result[6] = DVD_data[6]/DVS_data[6];
- result[7] = DVD_data[7]/DVS_data[7];
- result[8] = DVD_data[8]/DVS_data[8];
- result[9] = DVD_data[9]/DVS_data[9];
- result[10] = DVD_data[10]/DVS_data[10];
- result[11] = DVD_data[11]/DVS_data[11];
- result[12] = DVD_data[12]/DVS_data[12];
- result[13] = DVD_data[13]/DVS_data[13];
- result[14] = DVD_data[14]/DVS_data[14];
- result[15] = DVD_data[15]/DVS_data[15];
- GPIOB->ODR ^= 1<<5;
- GPIOB->ODR ^= 1<<5;
- i = 1000;while(i--);
- }
- }
复制代码
硬件除法器进行16次除法运算用时6.52us(96MHz):
图1 硬件除法器32次除法运算 软件进行32次除法运算用时42.29us(96MHz):
图2 软件32次除法运算 开方运算在电机控制里面也非常常见,例如矢量合成和滤波部分。MM32SPIN2x系列自带硬件开方器支持32位无符号整数的开平方。
硬件开方器包括1个32位被开方寄存器和1个16位的平方根寄存器,都是无符号整数。每一次写入被开方寄存器,会自动除法开方运算,在运算结束后,结果会写入到平方根寄存器里。如果在结束前读平方根寄存器,读操作会被暂停,直到结束才返回运算结果。
硬件开方器的配置极其简单,只需打开硬件开方器的时钟后,在运算时写入被开方数即可。软件运算使用C语言自带的math.h中的sqrt()开平方函数。
- u32 HWROOT_data[32] = {
- 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[32]; //商和余数
- 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[0];
- result[0] = HWROOT->ROOT;
- HWROOT->SQR = HWROOT_data[0];
- result[1] = HWROOT->ROOT;
- HWROOT->SQR = HWROOT_data[0];
- result[2] = HWROOT->ROOT;
- HWROOT->SQR = HWROOT_data[0];
- result[3] = HWROOT->ROOT;
- HWROOT->SQR = HWROOT_data[0];
- result[4] = HWROOT->ROOT;
- HWROOT->SQR = HWROOT_data[0];
- result[5] = HWROOT->ROOT;
- HWROOT->SQR = HWROOT_data[0];
- result[6] = HWROOT->ROOT;
- HWROOT->SQR = HWROOT_data[0];
- result[7] = HWROOT->ROOT;
- HWROOT->SQR = HWROOT_data[0];
- result[8] = HWROOT->ROOT;
- HWROOT->SQR = HWROOT_data[0];
- result[9] = HWROOT->ROOT;
- HWROOT->SQR = HWROOT_data[0];
- result[10] = HWROOT->ROOT;
- HWROOT->SQR = HWROOT_data[0];
- result[11] = HWROOT->ROOT;
- HWROOT->SQR = HWROOT_data[0];
- result[12] = HWROOT->ROOT;
- HWROOT->SQR = HWROOT_data[0];
- result[13] = HWROOT->ROOT;
- HWROOT->SQR = HWROOT_data[0];
- result[14] = HWROOT->ROOT;
- HWROOT->SQR = HWROOT_data[0];
- result[15] = HWROOT->ROOT;
- GPIOB->ODR ^= 1<<5;
- GPIOB->ODR ^= 1<<5;
- i = 1000;while(i--);
-
- GPIOB->ODR ^= 1<<5;
- GPIOB->ODR ^= 1<<5;
- result[0] = sqrt(HWROOT_data[0]);//软件开方运算
- result[1] = sqrt(HWROOT_data[1]);
- result[2] = sqrt(HWROOT_data[2]);
- result[3] = sqrt(HWROOT_data[3]);
- result[4] = sqrt(HWROOT_data[4]);
- result[5] = sqrt(HWROOT_data[5]);
- result[6] = sqrt(HWROOT_data[6]);
- result[7] = sqrt(HWROOT_data[7]);
- result[8] = sqrt(HWROOT_data[8]);
- result[9] = sqrt(HWROOT_data[9]);
- result[10] = sqrt(HWROOT_data[10]);
- result[11] = sqrt(HWROOT_data[11]);
- result[12] = sqrt(HWROOT_data[12]);
- result[13] = sqrt(HWROOT_data[13]);
- result[14] = sqrt(HWROOT_data[14]);
- result[15] = sqrt(HWROOT_data[15]);
- GPIOB->ODR ^= 1<<5;
- GPIOB->ODR ^= 1<<5;
- i = 1000;while(i--);
- }
- }
复制代码
硬件开方器执行16次开方运算用时5.44us(96MHz):
图三 硬件开方32次开方运算 软件执行16次开方运算用时238.22us(96MHz):
图四 软件32次开方运算 由此可见,硬件除法器和硬件开方在提升运算速度,降低MCU负担方面有极其显著的作用。
灵动微电子即将参加于2018年12月20-22日在深圳会展中心召开的“2018深圳国际电子展暨深圳国际嵌入式系统展”,届时灵动会给大家带来很多意想不到的惊喜,展位号:1C16,敬请期待!
关于灵动微电子 灵动微电子股份有限公司(股票代码:833448,股票简称:灵动微电)是国内专注于MCU产品与MCU应用方案的领先供应商,是中国工业及信息化部和上海市信息化办公室认定的集成电路设计企业,同时也是上海市认定的高新技术企业。自2011年3月成立至今,灵动微电子已经成功完成数百余MCU产品的设计及推广,灵动微电子目前已批量供货的基于ARMCortex-M0及Cortex-M3 内核的MCU产品包括:针对通用高性能市场的MM32F系列,针对超低功耗及安全应用的MM32L系列,具有多种无线连接功能的MM32W系列,电机驱动及控制专用的MM32SPIN系列,以及针对超小尺寸及超高集成度的MM32P系列等,以满足客户及市场多领域、多层次的丰富应用场景需求。
灵动微电子立足本土,洞悉市场,贴近客户,以为客户提供“保姆式”的全方位支持为特色,坚持“专业、可靠、便捷、高效”的服务理念,贯彻差异最大化,成本最优化的经营策略,不断强化自身生态价值,维护良好产品品牌。公司在销售初期就与客户充分接触,为客户提供产品整体解决方案,从产品功能定义、市场竞争力分析到算法整合、软件驱动、应用例程等都深入参与,为客户提供精准的市场分析和全面的应用方案,帮助客户把握好成功的每一个重要环节。
`
0
|
|
|
|