打印

PWM产生的源函数求解释啊?

[复制链接]
3898|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
554782398|  楼主 | 2014-4-15 13:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

void F281X_EV1_PWM_Update(PWMGEN *p)
{      
                int16 MPeriod;
        int32 Tmp;

// Compute the timer period (Q0) from the period modulation input (Q15)
        Tmp = (int32)p->PeriodMax*(int32)p->MfuncPeriod;           // Q15 = Q0*Q15
        MPeriod = (int16)(Tmp>>16) + (int16)(p->PeriodMax>>1);     // Q0 = (Q15->Q0)/2 + (Q0/2)
        EvaRegs.T1PR = MPeriod;  

// Compute the compare 1 (Q0) from the PWM 1&2 duty cycle ratio (Q15)
        Tmp = (int32)MPeriod*(int32)p->MfuncC1;                    // Q15 = Q0*Q15
        EvaRegs.CMPR1 = (int16)(Tmp>>16) + (int16)(MPeriod>>1);    // Q0 = (Q15->Q0)/2 + (Q0/2)

// Compute the compare 2 (Q0) from the PWM 3&4 duty cycle ratio (Q15)
        Tmp = (int32)MPeriod*(int32)p->MfuncC2;                   // Q15 = Q0*Q15
        EvaRegs.CMPR2 = (int16)(Tmp>>16) + (int16)(MPeriod>>1);   // Q0 = (Q15->Q0)/2 + (Q0/2)

// Compute the compare 3 (Q0) from the PWM 5&6 duty cycle ratio (Q15)
        Tmp = (int32)MPeriod*(int32)p->MfuncC3;                   // Q15 = Q0*Q15
        EvaRegs.CMPR3 = (int16)(Tmp>>16) + (int16)(MPeriod>>1);   // Q0 = (Q15->Q0)/2 + (Q0/2)
        }

这个函数中MfuncC1,MfuncC3,MfuncC3,是 svgendq模块产生的Ta,Tb,Tc。然后用于算三个寄存器的值。我的疑问是他怎么算的啊.....我看书上说的应该是CMPR3=Tc/时钟周期啊.....可是他这里怎么搞得啊?

相关帖子

沙发
zhangmangui| | 2014-4-15 22:38 | 只看该作者
// Compute the timer period (Q0) from the period modulation input (Q15)
        Tmp = (int32)p->PeriodMax*(int32)p->MfuncPeriod;           // Q15 = Q0*Q15
        MPeriod = (int16)(Tmp>>16) + (int16)(p->PeriodMax>>1);     // Q0 = (Q15->Q0)/2 + (Q0/2)
        EvaRegs.T1PR = MPeriod;

// Compute the compare 1 (Q0) from the PWM 1&2 duty cycle ratio (Q15)
        Tmp = (int32)MPeriod*(int32)p->MfuncC1;                    // Q15 = Q0*Q15
        EvaRegs.CMPR1 = (int16)(Tmp>>16) + (int16)(MPeriod>>1);    // Q0 = (Q15->Q0)/2 + (Q0/2)

// Compute the compare 2 (Q0) from the PWM 3&4 duty cycle ratio (Q15)
        Tmp = (int32)MPeriod*(int32)p->MfuncC2;                   // Q15 = Q0*Q15
        EvaRegs.CMPR2 = (int16)(Tmp>>16) + (int16)(MPeriod>>1);   // Q0 = (Q15->Q0)/2 + (Q0/2)

// Compute the compare 3 (Q0) from the PWM 5&6 duty cycle ratio (Q15)
        Tmp = (int32)MPeriod*(int32)p->MfuncC3;                   // Q15 = Q0*Q15
        EvaRegs.CMPR3 = (int16)(Tmp>>16) + (int16)(MPeriod>>1);   // Q0 = (Q15->Q0)/2 + (Q0/2)

蓝色部分的语句让我很费解,经过查找资料和自己的理解,总算看明白了。现解释如下:

Tmp = (int32)p->PeriodMax*(int32)p->MfuncPeriod;           // Q15 = Q0*Q15
MfuncPeriod的范围是-1~1(Q15)格式, PeriodMax 是一个较大的整数,我们假设是3000,那么Tmp的范围应该是
-3000~3000,但是PMW的周期必须为正整数,即0到 PeriodMax,怎么把-3000~3000转换成0~ PeriodMax呢?
MPeriod = (int16)(Tmp>>16) + (int16)(p->PeriodMax>>1);     // Q0 = (Q15->Q0)/2 + (Q0/2)
这条语句就是实现上述功能的。Tmp首先除于2,范围变为-1500~1500,然后在偏移1500(+PeriodMax>>1),此时范围是0~3000,实现了上述转换。
EvaRegs.CMPR1 = (int16)(Tmp>>16) + (int16)(MPeriod>>1);    // Q0 = (Q15->Q0)/2 + (Q0/2)
EvaRegs.CMPR2 = (int16)(Tmp>>16) + (int16)(MPeriod>>1);   // Q0 = (Q15->Q0)/2 + (Q0/2)
EvaRegs.CMPR3 = (int16)(Tmp>>16) + (int16)(MPeriod>>1);   // Q0 = (Q15->Q0)/2 + (Q0/2)
这三条语句,与上面的理解类似,但是要注意,此时的 PWM 1&2 duty cycle ratio 也就是MfuncC1是经过处理的一个变量,我们知道占空比是不能出现负数的,但是此时的MfuncC1的范围为什么是-1~1呢?这个和SVGEN_DQ的实现有关,在其源代码的结束,有三条语句,
// Convert the unsigned GLOBAL_Q format (ranged (0,1)) -> signed GLOBAL_Q format (ranged (-1,1))
    v->Ta = _IQmpy(_IQ(2.0),(v->Ta-_IQ(0.5)));
    v->Tb = _IQmpy(_IQ(2.0),(v->Tb-_IQ(0.5)));
    v->Tc = _IQmpy(_IQ(2.0),(v->Tc-_IQ(0.5)));
这三条语句实现了占空比由(0,1)到(-1,-1)的转换。
此时,可以总结下该问题了
1,Tmp = (int32)p->PeriodMax*(int32)p->MfuncPeriod;           // Q15 = Q0*Q15
该条语句的作用,PWM周期PeriodMax乘以其占空比(低电平占周期的百分数),得到比较寄存器的值,但因为此时的占空比经过范围变换处理,所以还不是真正的比较寄存器的值
2,EvaRegs.CMPR1 = (int16)(Tmp>>16) + (int16)(MPeriod>>1);    // Q0 = (Q15->Q0)/2 + (Q0/2)
把上条语句得到的值Tmp除以2,实现占空比由(-1,1)到(-0.5,0,5)的还原,然后右移15位,也就是取整,将该数从Q15格式转换成Q0格式,然后加上0.5(对应MPeriod>>1)的偏移,把占空比还原到(0,1),此时的结果就是比较寄存器的值。
举个例子,如果PeriodMax是3000,MfuncPeriod的范围是(-1,1),Tmp的范围是(-3000,3000),然后我们把Tmp右移1位,此时Tmp的范围是(-1500,1500),然后加上Mperiod右移1位的值,即加上1500,此时Tmp的范围变为(0,3000),得到了比较寄存器的值

使用特权

评论回复
板凳
zhangmangui| | 2014-4-15 22:39 | 只看该作者
上面分享来自网络收集   供大家学习使用

使用特权

评论回复
地板
zhangmangui| | 2014-4-15 22:39 | 只看该作者
上面分享来自网络收集   供大家学习使用

使用特权

评论回复
5
frankyeah| | 2014-7-28 14:44 | 只看该作者
同求!
按照版主提供的资料,可以得出:
EvaRegs.T1PR=PeriodMax- PeriodMax/65536
这个该怎么理解呢?
不知道楼主的问题解决了没,分享一下心得呐


使用特权

评论回复
6
siyida| | 2014-7-28 16:01 | 只看该作者
学习

使用特权

评论回复
7
frankyeah| | 2014-7-28 16:14 | 只看该作者

http_//masust.blog.163.com/blog/static/14695408420117319362365/
看了这个博客以及博主回复的内容,总算明白了一大部分,困扰了我两天的问题啊。
唉,我还没权利发表链接呢。把第一个_字符改写成:就可以访问了。

使用特权

评论回复
8
悠然33| | 2017-3-31 10:28 | 只看该作者
zhangmangui 发表于 2014-4-15 22:38
// Compute the timer period (Q0) from the period modulation input (Q15)
        Tmp = (int32)p->Peri ...

#define F281X_EV1_FC_PWM_GEN {1000,   \
                                  0x7FFF, \
                                  0x4000, \
                                  0x4000, \
                                  0x4000, \
                                  (void (*)(Uint32))F281X_EV1_PWM_Init,  \
                                  (void (*)(Uint32))F281X_EV1_PWM_Update \可是初始值是0X7FFF,怎么是-1到1 呢?

使用特权

评论回复
9
zhangmangui| | 2017-3-31 21:02 | 只看该作者
悠然33 发表于 2017-3-31 10:28
#define F281X_EV1_FC_PWM_GEN {1000,   \
                                  0x7FFF, \
                ...

7FFF  就是中间值   也就是x轴

使用特权

评论回复
10
zhangmangui| | 2017-3-31 21:03 | 只看该作者
悠然33 发表于 2017-3-31 10:28
#define F281X_EV1_FC_PWM_GEN {1000,   \
                                  0x7FFF, \
                ...

MCU输出的肯定是波形    输出后经滤波   变光滑
然后隔直   就成了正负的正弦波

使用特权

评论回复
11
悠然33| | 2017-4-1 09:27 | 只看该作者
本帖最后由 悠然33 于 2017-4-1 09:28 编辑
zhangmangui 发表于 2017-3-31 21:02
7FFF  就是中间值   也就是x轴

谢谢讲解,是我理解错了,我忘记7FFF是Q格式表示的,一直还看成是16进制的

使用特权

评论回复
12
zhangmangui| | 2017-4-3 22:52 | 只看该作者
悠然33 发表于 2017-4-1 09:27
谢谢讲解,是我理解错了,我忘记7FFF是Q格式表示的,一直还看成是16进制的 ...

多分享啊

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

3

帖子

0

粉丝