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);相关疑问,求解答

__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;

x 出现错误。请重试或与管理员联系。