MM32SPIN2x 電機(jī)MCU功能特色:硬件除法器與硬件
上一章節(jié)中已經(jīng)教大家如何使用MM32SPIN2x的PWM控制?刂乒δ,本章節(jié)將與大家一起配置硬件除法器和硬件開方器。
除法和開方是非常消耗時(shí)間的運(yùn)算,而在電機(jī)控制算法中,乘除法和平方根運(yùn)算在電機(jī)運(yùn)算中使用頻率較高。為了提高M(jìn)CU的工作效率,MM32SPIN2x了內(nèi)嵌硬件32bit硬件除法器和32bit硬件乘法器,能自動(dòng)執(zhí)行有符號(hào)或32位整數(shù)乘除法和開根號(hào)運(yùn)算。硬件運(yùn)算大大提升了應(yīng)用程序的效率,減少了代碼運(yùn)算量,相比軟件它們對(duì)于特定問題計(jì)算速度更快,位寬更大。
下面和大家一起配置如何使用硬件除法器和硬件開方進(jìn)行運(yùn)算。
硬件除法單元包括六個(gè)32位寄存器,四個(gè)數(shù)據(jù)寄存器分別為被除數(shù)、除數(shù)、商和余數(shù),以及一個(gè)控制寄存器和一個(gè)狀態(tài)寄存器。在使用時(shí),先打開硬件除法器時(shí)鐘使能,然后配置控制寄存器(HWDIV_CR)選擇是否使能除零溢出中斷和有無符號(hào)除法,然后往被除數(shù)寄存器和除數(shù)寄存器中寫入數(shù)據(jù),每一次寫入除數(shù)寄存器,會(huì)自動(dòng)觸發(fā)除法運(yùn)算,在運(yùn)算結(jié)束后,結(jié)果會(huì)寫入到商和余數(shù)寄存器里。如果在運(yùn)算未結(jié)束前讀商寄存器、余數(shù)寄存器或者狀態(tài)寄存器,讀操作會(huì)被暫停,直到運(yùn)算結(jié)束才會(huì)返回運(yùn)算結(jié)果。特別的,如果除數(shù)為零,會(huì)產(chǎn)生溢出中斷標(biāo)志位。寄存器詳細(xì)定義請(qǐng)參考MM32SPIN2x_p用戶手冊(cè)。
硬件除法器初始化配置如下:
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_HWDIV, ENABLE); //使能除法器時(shí)鐘
HWDIV->DIVCON |= (DIV_UNSIGN ); //無符號(hào)除法,不使能除零中斷
為了驗(yàn)證硬件除法器的效率,在主函數(shù)中分別使用硬件除法器和軟件除法器進(jìn)行16次除法運(yùn)算,不使用while是為了避免多余的指令占用時(shí)間。
主函數(shù)如下:
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,
};//除數(shù)數(shù)組
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;
//硬件除法器運(yùn)算
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;
//軟件除法器運(yùn)算
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--);
}
}
硬件除法器進(jìn)行16次除法運(yùn)算用時(shí)6.52us(96MHz):
圖1 硬件除法器32次除法運(yùn)算
軟件進(jìn)行32次除法運(yùn)算用時(shí)42.29us(96MHz):
圖2 軟件32次除法運(yùn)算
開方運(yùn)算在電機(jī)控制里面也非常常見,例如矢量合成和濾波部分。MM32SPIN2x系列自帶硬件開方器支持32位無符號(hào)整數(shù)的開平方。
硬件開方器包括1個(gè)32位被開方寄存器和1個(gè)16位的平方根寄存器,都是無符號(hào)整數(shù)。每一次寫入被開方寄存器,會(huì)自動(dòng)除法開方運(yùn)算,在運(yùn)算結(jié)束后,結(jié)果會(huì)寫入到平方根寄存器里。如果在結(jié)束前讀平方根寄存器,讀操作會(huì)被暫停,直到結(jié)束才返回運(yùn)算結(jié)果。
硬件開方器的配置極其簡(jiǎn)單,只需打開硬件開方器的時(shí)鐘后,在運(yùn)算時(shí)寫入被開方數(shù)即可。軟件運(yùn)算使用C語(yǔ)言自帶的math.h中的sqrt()開平方函數(shù)。
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 ,
};//被開方數(shù)數(shù)組
u32 result[32]; //商和余數(shù)
int main (void)
{
u32 i ;
IO_Init();
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_HWROOT,ENABLE);
while(1)
{
GPIOB->ODR ^= 1<<5;
GPIOB->ODR ^= 1<<5;
//硬件開方運(yùn)算
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]);//軟件開方運(yùn)算
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--);
}
}
硬件開方器執(zhí)行16次開方運(yùn)算用時(shí)5.44us(96MHz):
圖三 硬件開方32次開方運(yùn)算
軟件執(zhí)行16次開方運(yùn)算用時(shí)238.22us(96MHz):
圖四 軟件32次開方運(yùn)算
由此可見,硬件除法器和硬件開方在提升運(yùn)算速度,降低MCU負(fù)擔(dān)方面有極其顯著的作用。
編輯:admin 最后修改時(shí)間:2018-12-27