This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
__qmpy32by16(long src32,int src16,int q)汇编源码如下:
long __qmpy32by16(long src32, int src16, int q);
CLRC OVM ;Extended precision DSP Q math. Different code is generated based on the value of q.
MOV T, src16 + 0
MPYXU P, T, src32 + 0
MPY P, T, src32 + 1
If q = 31, 30: SPM q − 30
SFR ACC, #46 − q
ADDL ACC, P
If q = 29 through 14: SPM 0
SFR ACC, #16
ADDL ACC, P
SFR ACC, #30 − q
If q = 13 through 0: SPM 0
SFR ACC, #16
ADDL ACC, P
SFR ACC, #16
SFR ACC, #14 – q
这里有一个疑问,就是这一句MPYXU P, T, src32 + 0,实际在CCS上看到的的汇编并不是P寄存器,而是ACC!相关的指令也对着指令集上的解释学习了,最后自己的理解是ACC=(ACC>>15)+(P<<1) ; 这里ACC=src32*src16, P=src16*(src32+1) ;为什么要加1???
但是实际上这个内部定义函数的结果不应该是Q15=Q0*Q30<<(46-31)吗???
在eQEP源码中q=31
求解答,我的理解是不是错的????谢谢!
补充一下,我在CCS上编译出来的反汇编是这样的,具体如下:
p->MechTheta = __qmpy32by16(p->MechScaler,(int16)p->RawTheta,31);
MOVL XAR4 ,*-SP[2] //在刚进入这个子函数的时候,*-SP[2]便指向了QEP结构体变量的入口地址,这里使XAR4和XAR5都指向QEP结构体的入口地址。
MOVL XAR5 , *-SP[2] //之后根据结构体变量对结构体成员的定义,包括成员顺序和成员数据类型,加上相应的地址偏移量即可指向存放实参的地址。
ADDB XAR4 , #10 //比如这里加上10个地址偏移量之后,就指向了 实参MechScaler。
CLRC OVM //记住地址偏移量是和结构体变量的成员顺序及成员数据类型相关的!!!是为了准确找到实参存放的地址!
SETC SXM
MOV T , *+XAR5[AR0] /./AR0=8,也就是入口地址加上8个地址偏移量,指向存放实参RawTheta的地址,并将实参RawTheta存放在T寄存器中。
MPYXU ACC , T , *+XAR4[0] //*+XAR4[0]指向的是存放实参MechScaler的低16位的值。
MPY P , T ,*XAR4[1] //*+XAR4[1]指向的是存放实参MechScaler的高16位的值,直接与T的值相乘,相当于将实参MechScaler右移16位,再与实参
//RawTheta相乘。
MOVL XAR4 , *-SP[2] //使XAR4重新指向QEP结构体变量的初始地址,方便后面寻址赋值,也就是把结果存在MechTheta 中。
SPM 1 //设置PM值为1,调用P寄存器时,会使其值左移1位,相当于P值右移了15位。
SFR ACC , 15 //ACC右移15位。
ADDL ACC ,P <<PM //将其存放在两个内存单元中的值恢复,实现Q15=Q30*Q0>>15的功能,这里DSP一个内存单元只能存放16位的数据。
MOVL *+XAR4[2] ,ACC //将结果赋给MechTheta,*+XAR4[2]指向的是存放MechTheta的地址。
以上内容我有整理成一份详细的文档,如有需要请邮件1016822780@qq.com
补充QEP结构体变量的定义
typedef struct {
int32 ElecTheta; // Output: Motor Electrical angle (Q24)
int32 MechTheta; // Output: Motor Mechanical Angle (Q24)
Uint16 DirectionQep; // Output: Motor rotation direction (Q0)
Uint16 QepPeriod; // Output: Capture period of QEP signal in number of EQEP capture timer (QCTMR) period (Q0)
Uint32 QepCountIndex; // Variable: Encoder counter index (Q0)
int32 RawTheta; // Variable: Raw angle from EQEP Postiion counter (Q0)
Uint32 MechScaler; // Parameter: 0.9999/total count (Q30)
Uint16 LineEncoder; // Parameter: Number of line encoder (Q0)
Uint16 PolePairs; // Parameter: Number of pole pairs (Q0)
int32 CalibratedAngle; // Parameter: Raw angular offset between encoder index and phase a (Q0)
Uint16 IndexSyncFlag; // Output: Index sync status (Q0)
void (*init)(); // Pointer to the init function
void (*calc)(); // Pointer to the calc function
} QEP;