MSP430程序库十三硬件乘法器使用资料.docx
《MSP430程序库十三硬件乘法器使用资料.docx》由会员分享,可在线阅读,更多相关《MSP430程序库十三硬件乘法器使用资料.docx(10页珍藏版)》请在冰点文库上搜索。
MSP430程序库十三硬件乘法器使用资料
MSP430程序库<十三>硬件乘法器使用
硬件乘法器不占用CPU周期,有硬件实现,速度比软件实现的乘法速度快很多。
msp430f14x、msp430f16x中都含有硬件乘法器模块,方便用户需要速度的时候使用。
∙硬件介绍:
在MSP430系列单片机中,硬件乘法器是外围模块,而不是CPU内核的一部分;所以它的活动与否与CPU的活动与否无关,它的寄存器和其他的外围寄存器一样通过CPU指令读写。
硬件乘法器模块支持一下功能:
无符号乘法、有符号乘法、无符号乘加、有符号乘加;可以支持16*1616*88*168*8bits的乘法。
硬件乘法器的模块框图如下:
硬件乘法器模块的四种操作类型(无符号乘法、有符号乘法、无符号乘加、有符号乘加)是由写入的第一个操作数的位置决定的。
这个模块有两个操作数寄存器:
OP1和OP2、三个结果寄存器RESLO,RESHI,和SUMEXT。
RESLO寄存器存储结果的低字(低16位);RESHI寄存器存储结果的高字(高16位);SUMEXT寄存器存储结果的有关信息。
结果在3个时钟周期后即可完成;写入OP2后的下一条指令即可读取结果,有一种情况例外:
用间接寻址方式访问结果。
用间接寻址方式访问结果时,读取结果之前需要有一条NOP指令。
操作数OP1有四个地址(MPY:
0130hMPYS:
0132hMAC:
0134hMACS:
0136h),这四个寄存器用来选择乘法的操作模式。
写入第一个操作数寄存器决定用哪种操作:
无符号用符号等,但是不启动相乘操作;写入第二个操作数寄存器启动相乘的操作。
计算完成后结果存入寄存器RESLO,RESHI,和SUMEXT。
操作数1的四个地址对应的操作:
OP1AddressRegisterNameOperation
0130hMPYUnsignedmultiply(无符号乘法)
0132hMPYSSignedmultiply(有符号乘法)
0134hMACUnsignedmultiplyaccumulate(无符号乘加)
0136hMACSSignedmultiplyaccumulate(有符号乘加)
四种操作模式下高位结果寄存器的内容如下:
ModeRESHIContents
MPYUpper16-bitsoftheresult
MPYSTheMSBisthesignoftheresult.Theremainingbitsaretheupper
15-bitsoftheresult.Two’scomplementnotationisusedfortheresult.
MACUpper16-bitsoftheresult
MACSUpper16-bitsoftheresult.Two’scomplementnotationisusedfortheresult.
四种操作模式SUMEXT寄存器的内容:
ModeSUMEXT
MPYSUMEXTisalways0000h
MPYSSUMEXTcontainstheextendedsignoftheresult
00000hResultwaspositiveorzero
0FFFFhResultwasnegative
MACSUMEXTcontainsthecarryoftheresult
0000hNocarryforresult
0001hResulthasacarry
MACSSUMEXTcontainstheextendedsignoftheresult
00000hResultwaspositiveorzero
0FFFFhResultwasnegative
连续乘法运算时,如果操作数1不需改变就可以运算,则可以不需要重新写入和以保存内容相同的数;但OP2必须重新写入以启动乘法运算。
MACSUnderflowandOverflow(MACS时的上溢和下溢):
硬件乘法器不检测有符号乘加时运算结果的上溢出和下溢出。
结果的正数范围:
0到7FFFFFFFh;负数范围:
0FFFFFFFFh到80000000h。
下溢出是两个负数的和结果寄存器得到的是正数,上溢出是两个正数的和结果寄存器得到的是负数。
SUMEXT寄存器存储有结果的符号,可以根据它判断是否溢出(0000h负数和则上溢0FFFFh正数和则下溢)。
使用时程序必须合适的检测、处理MACS的溢出情况。
程序示例(用户指南上给出的汇编示例):
所有乘数模式的例子如下。
所有的8x8模式使用的寄存器的绝对地址,因为汇编器将不允许B访问到字寄存器时使用标准定义的文件标签。
;16x16UnsignedMultiply
MOV#01234h,&MPY;Loadfirstoperand
MOV#05678h,&OP2;Loadsecondoperand
;...;Processresults
;8x8UnsignedMultiply.Absoluteaddressing.
MOV.B#012h,&0130h;Loadfirstoperand
MOV.B#034h,&0138h;Load2ndoperand
;...;Processresults
;16x16SignedMultiply
MOV#01234h,&MPYS;Loadfirstoperand
MOV#05678h,&OP2;Load2ndoperand
;...;Processresults
;8x8SignedMultiply.Absoluteaddressing.
MOV.B#012h,&0132h;Loadfirstoperand
SXT&MPYS;Signextendfirstoperand
MOV.B#034h,&0138h;Load2ndoperand
SXT&OP2;Signextend2ndoperand
;(triggers2ndmultiplication)
;...;Processresults
;16x16UnsignedMultiplyAccumulate
MOV#01234h,&MAC;Loadfirstoperand
MOV#05678h,&OP2;Load2ndoperand
;...;Processresults
;8x8UnsignedMultiplyAccumulate.Absoluteaddressing
MOV.B#012h,&0134h;Loadfirstoperand
MOV.B#034h,&0138h;Load2ndoperand
;...;Processresults
;16x16SignedMultiplyAccumulate
MOV#01234h,&MACS;Loadfirstoperand
MOV#05678h,&OP2;Load2ndoperand
;...;Processresults
;8x8SignedMultiplyAccumulate.Absoluteaddressing
MOV.B#012h,&0136h;Loadfirstoperand
SXT&MACS;Signextendfirstoperand
MOV.B#034h,R5;Temp.locationfor2ndoperand
SXTR5;Signextend2ndoperand
MOVR5,&OP2;Load2ndoperand
;...;Processresults
上面的程序虽然和标准的汇编差异比较大,但是有一定汇编基础的人还是很容易就能够看懂。
这里的程序给出了多种方式写入操作数寄存器。
间接寻址结果寄存器时,在写入OP2操作数启动乘法后,至少需要一个指令的延迟后才能访问结果寄存器RESLO等;直接寻址时可以写入OP2后,下一条指令即可读取结果。
示例程序(汇编):
;Accessmultiplierresultswithindirectaddressing
MOV#RESLO,R5;RESLOaddressinR5forindirect
MOV&OPER1,&MPY;Load1stoperand
MOV&OPER2,&OP2;Load2ndoperand
NOP;Needonecycle写入两个操作数乘法运算开始后需要一个NOP
MOV@R5+,&xxx;MoveRESLO
MOV@R5,&xxx;MoveRESHI
如果在写入OP1和写入OP2之间产生了中断,中断响应后,源操作数的计算模式丢失;运算结果不确定。
为了避免这种情况的发生,在写入操作数时禁止中断或在中断响应函数中不使用硬件乘法器。
如:
;Disableinterruptsbeforeusingthehardwaremultiplier
DINT;Disableinterrupts
NOP;RequiredforDINT
MOV#xxh,&MPY;Load1stoperand
MOV#xxh,&OP2;Load2ndoperand
EINT;Interruptsmaybeenablebefore
;Processresults
硬件部分就说这么多了,有什么不大明白的可以参考用户指南。
∙使用示例:
我的程序仅仅是用C语言演示硬件乘法器的使用。
程序主要内容如下:
#include
/****************************************************************************
*名称:
main主程序
*功能:
硬件乘法器程序库使用演示
*入口参数:
无
*出口参数:
无
****************************************************************************/
voidmain(void)
{
//Stopwatchdogtimertopreventtimeoutreset
WDTCTL=WDTPW+WDTHOLD;
ClkInit();
/*把硬件乘法器的寄存器放到watch窗口观察是否变化
inta=0;
a=5*6;
*/
//测试无符号乘法
MPY=65535;
OP2=2;
//有符号乘法
MPYS=65535;
OP2=2;
//无符号乘加
MAC=65535;
OP2=2;
//有符号乘加
MACS=65535;
OP2=2;
LPM0;
}
程序演示了4中乘法模式:
使用时单步调试,观察硬件乘法器的有关寄存器。
如:
硬件乘法器运算速度很快,只需3个时钟周期;这里IAR单步调试时,OP2赋值结束,在watch窗口马上就可以看到运算结果。
其他三种模式类似。
注释掉的这部分是我用来检测IAR编译程序是否使用硬件乘法器进行测试。
默认情况下,乘法应该是用硬件乘法器运算的。
默认的设置如下:
硬件乘法器是选中的,这时应该是使用硬件乘法器的,但是我的调试结果显示它没有使用硬件乘法器,截图下:
运行后乘法器相关位没有对应变化,如果使用的话,应该变化。
硬件乘法器不选中时,寄存器也没有相应变化,从这看,IAR没有使用硬件乘法器;也许程序没有优化太多或是debug版本不使用硬件乘法器。
如果需要直接使用硬件乘法器,有必要时把设置的硬件乘法器去掉,以防冲突。
下面是直接使用硬件乘法器的一个实例:
#include"msp430x16x.h"
unsignedintResult[7];
unsignedcharData1[7];
unsignedcharData2[7];
voidmain(void)
{
unsignedchari;
WDTCTL=WDTPW+WDTHOLD;//关看门狗
for(i=0;i<7;i++)
{
Data1[i]=10*i;//对两数组赋值
Data2[i]=25*i;
}
for(i=0;i<7;i++)
{
MPY=Data1[i];
OP2=Data2[i];
_NOP();//延迟
_NOP();
_NOP();
Result[i]=RESLO;//保存结果,由于是8×8型,所以未用到RESHI;
}
}
这个程序用无符号乘法运算,结果存入结果数组中。
值的注意的是程序中的3个NOP,这里NOP不需要,根据头文件推测,IAR编译器应该使用的是直接寻址方式,可以不要。
如果不太放心,一个NOP即可,即便用的是间接寻址,一个NOP的延迟已经足够。
硬件乘法器一般不会像上面的程序那么使用,如果这样就太浪费了;还不如直接用*操作符来的简便;硬件乘法器主要用来对时间要求苛刻的情况。
如:
用430进行数字滤波,快速傅里叶变换等。
ti有一篇应用笔记介绍的就是用msp430f169实现数字滤波方案。
硬件乘法器就到这里了,希望对大家有所帮助。
有什么不足之处,欢迎拍砖讨论。